OSDN Git Service

Omniauth Support
authorFlorian Unglaub <florian.unglaub@nix-wie-weg.de>
Fri, 3 Aug 2012 15:27:39 +0000 (17:27 +0200)
committerFlorian Unglaub <florian.unglaub@nix-wie-weg.de>
Fri, 17 Aug 2012 13:20:55 +0000 (15:20 +0200)
20 files changed:
Gemfile
Gemfile.lock
app/assets/stylesheets/auth_methods.scss [new file with mode: 0644]
app/assets/stylesheets/main.scss
app/controllers/omniauth_callbacks_controller.rb
app/helpers/application_helper.rb
app/views/devise/sessions/new.html.erb
app/views/layouts/profile.html.haml
app/views/profile/password.html.haml
app/views/profile/show.html.haml
config/gitlab.yml.example
config/initializers/1_settings.rb
db/migrate/20120803152018_add_provider_and_uid_to_users.rb [new file with mode: 0644]
db/schema.rb
vendor/assets/images/authbuttons/github_32.png [new file with mode: 0644]
vendor/assets/images/authbuttons/github_64.png [new file with mode: 0644]
vendor/assets/images/authbuttons/google_32.png [new file with mode: 0644]
vendor/assets/images/authbuttons/google_64.png [new file with mode: 0644]
vendor/assets/images/authbuttons/twitter_32.png [new file with mode: 0644]
vendor/assets/images/authbuttons/twitter_64.png [new file with mode: 0644]

diff --git a/Gemfile b/Gemfile
index d2a5728..12610b6 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -8,6 +8,10 @@ gem "mysql2"
 
 # Auth
 gem "devise", "~> 2.1.0"
+gem 'omniauth'
+gem 'omniauth-google-oauth2'
+gem 'omniauth-twitter'
+gem 'omniauth-github'
 
 # GITLAB patched libs
 gem "grit",          :git => "https://github.com/gitlabhq/grit.git",            :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
index 7356c35..b34f401 100644 (file)
@@ -166,6 +166,8 @@ GEM
     eventmachine (0.12.10)
     execjs (1.4.0)
       multi_json (~> 1.0)
+    faraday (0.8.1)
+      multipart-post (~> 1.1)
     ffaker (1.14.0)
     ffi (1.0.11)
     foreman (0.47.0)
@@ -191,6 +193,7 @@ GEM
     httparty (0.8.3)
       multi_json (~> 1.0)
       multi_xml
+    httpauth (0.1)
     i18n (0.6.0)
     journey (1.0.4)
     jquery-rails (2.0.2)
@@ -200,6 +203,8 @@ GEM
       jquery-rails
       railties (>= 3.1.0)
     json (1.7.4)
+    jwt (0.1.5)
+      multi_json (>= 1.0)
     kaminari (0.13.0)
       actionpack (>= 3.0.0)
       activesupport (>= 3.0.0)
@@ -223,12 +228,35 @@ GEM
       sprockets (~> 2.0)
     multi_json (1.3.6)
     multi_xml (0.5.1)
+    multipart-post (1.1.5)
     mysql2 (0.3.11)
     net-ldap (0.2.2)
     nokogiri (1.5.3)
+    oauth (0.4.6)
+    oauth2 (0.8.0)
+      faraday (~> 0.8)
+      httpauth (~> 0.1)
+      jwt (~> 0.1.4)
+      multi_json (~> 1.0)
+      rack (~> 1.2)
     omniauth (1.1.0)
       hashie (~> 1.2)
       rack
+    omniauth-github (1.0.1)
+      omniauth (~> 1.0)
+      omniauth-oauth2 (~> 1.0)
+    omniauth-google-oauth2 (0.1.13)
+      omniauth (~> 1.0)
+      omniauth-oauth2
+    omniauth-oauth (1.0.1)
+      oauth
+      omniauth (~> 1.0)
+    omniauth-oauth2 (1.1.0)
+      oauth2 (~> 0.8.0)
+      omniauth (~> 1.0)
+    omniauth-twitter (0.0.12)
+      multi_json (~> 1.3)
+      omniauth-oauth (~> 1.0)
     orm_adapter (0.3.0)
     polyglot (0.3.3)
     posix-spawn (0.3.6)
@@ -411,7 +439,11 @@ DEPENDENCIES
   minitest (>= 2.10)
   modernizr (= 2.5.3)
   mysql2
+  omniauth
+  omniauth-github
+  omniauth-google-oauth2
   omniauth-ldap!
+  omniauth-twitter
   pry
   pygments.rb!
   rack-mini-profiler
diff --git a/app/assets/stylesheets/auth_methods.scss b/app/assets/stylesheets/auth_methods.scss
new file mode 100644 (file)
index 0000000..ed6f5b0
--- /dev/null
@@ -0,0 +1,10 @@
+.auth_methods {
+  &ul {
+    margin: 0;
+    text-align:center;
+    padding: 5px;
+    &li {
+      display: inline;
+    }
+  }
+}
index 5613f1e..0e3de4e 100644 (file)
@@ -3,8 +3,8 @@
 
 /** GITLAB colors **/
 $text_color:#222;
-$lite_text_color: #666; 
-$link_color:#2A79A3; 
+$lite_text_color: #666;
+$link_color:#2A79A3;
 $active_link_color:#2FA0BB;
 $active_bg_color:#79C3E0;
 $active_bd_color: #2FA0BB;
@@ -31,7 +31,7 @@ $hover: #FDF5D9;
   box-shadow: 0 0 3px #ddd;
 }
 
-@mixin solid_shade { 
+@mixin solid_shade {
   -moz-box-shadow: 0 0 0 3px #eee;
   -webkit-box-shadow: 0 0 0 3px #eee;
   box-shadow: 0 0 0 3px #eee;
@@ -73,21 +73,21 @@ $hover: #FDF5D9;
 
 
 /**
- * Header of application. 
+ * Header of application.
  * Contain application logo, search panel, profile icon
  */
 @import "sections/header.scss";
 
 /**
- * Navigation menu of application. 
+ * Navigation menu of application.
  * Panel with links to pages depends on project, profile or admin area
  */
 @import "sections/nav.scss";
 
 /**
- * This file represent some UI that can be changed 
- * during web app restyle or theme select. 
- * 
+ * This file represent some UI that can be changed
+ * during web app restyle or theme select.
+ *
  * Next items should be placed there
  * - link, button colors
  * - header restyles
@@ -118,11 +118,11 @@ $hover: #FDF5D9;
  * Most of application styles placed here.
  * This file represent common UI that should not be changed between themes
  * or project restyling like form width or user avatar class or commit title
- * 
+ *
  * TODO: clean it
  */
 @import "common.scss";
-
+@import "auth_methods.scss";
 
 /**
  * Styles related to specific part of app
@@ -140,17 +140,17 @@ $hover: #FDF5D9;
 @import "ref_select.scss";
 
 /**
- * Code (files list) styles. Browsing project files there 
+ * Code (files list) styles. Browsing project files there
  */
 @import "sections/tree.scss";
 
 /**
- * This file represent notes(comments) styles 
+ * This file represent notes(comments) styles
  */
 @import "sections/notes.scss";
 
 /**
- * Devise styles 
+ * Devise styles
  */
 @import "sections/login.scss";
 
index d19931e..84e578a 100644 (file)
@@ -9,7 +9,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
     error ||= env["omniauth.error.type"].to_s
     error.to_s.humanize if error
   end
+
   def ldap
     # We only find ourselves here if the authentication to LDAP was successful.
     info = request.env["omniauth.auth"]["info"]
@@ -20,4 +20,34 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
     sign_in_and_redirect @user
   end
 
+   Settings.omniauth_providers.each do |provider|
+    define_method provider['name'] do
+      handle_omniauth
+    end
+  end
+
+  private
+
+  def handle_omniauth
+    oauth = request.env['omniauth.auth']
+    provider, uid = oauth['provider'], oauth['uid']
+
+    if current_user
+      # Change a logged-in user's authentication method:
+      current_user.uid = uid
+      current_user.provider = provider
+      current_user.save
+      redirect_to profile_path
+    else
+      @user = User.find_by_provider_and_uid(provider, uid)
+
+      if @user
+        sign_in_and_redirect @user
+      else
+        flash[:notice] = "There's no such user!"
+        redirect_to new_user_session_path
+      end
+    end
+  end
+
 end
index 51569b0..8a457ce 100644 (file)
@@ -75,16 +75,16 @@ module ApplicationHelper
   end
 
   def show_last_push_widget?(event)
-    event && 
+    event &&
       event.last_push_to_non_root? &&
       !event.rm_ref? &&
-      event.project && 
+      event.project &&
       event.project.merge_requests_enabled
   end
 
   def tab_class(tab_key)
     active = case tab_key
-             
+
              # Project Area
              when :wall; wall_tab?
              when :wiki; controller.controller_name == "wikis"
@@ -123,4 +123,9 @@ module ApplicationHelper
   def hexdigest(string)
     Digest::SHA1.hexdigest string
   end
+
+  def authbutton(provider, size = 64)
+    image_tag("authbuttons/#{provider.to_s.split('_').first}_#{size}.png",
+               alt: "Sign in with #{provider.to_s.titleize}" )
+  end
 end
index a038386..6b334b8 100644 (file)
     <div class="right"> <%= render :partial => "devise/shared/links" %></div>
 
     <%- if devise_mapping.omniauthable? %>
-      <%- resource_class.omniauth_providers.each do |provider| %>
-        <hr/>
-        <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary" %><br />
-      <% end -%>
+      <hr/>
+      <div class="auth_methods">
+        <ul>
+          <%- resource_class.omniauth_providers.each do |provider| %>
+          <li><%= link_to authbutton(provider),
+                   omniauth_authorize_path(resource_name, provider) %></li>
+          <% end -%>
+        </ul>
+      </div>
     <% end -%>
 
   <% end %>
index b624415..810b346 100644 (file)
@@ -10,7 +10,7 @@
           = link_to "Profile", profile_path
 
         %li{class: tab_class(:password)}
-          = link_to "Password", profile_password_path
+          = link_to "Authentication", profile_password_path
 
         %li{class: tab_class(:ssh_keys)}
           = link_to keys_path do
index 257dacb..1d4d468 100644 (file)
@@ -1,19 +1,31 @@
 %h3.page_title Password
 %hr
+
 = form_for @user, url: profile_password_path, method: :put do |f|
-  .data
-    %p.slead After successful password update you will be redirected to login page where you should login with new password
-    -if @user.errors.any?
-      .alert-message.block-message.error
-        %ul
-          - @user.errors.full_messages.each do |msg|
-            %li= msg
+  .row
+    .span7
+      .data
+        %p.slead After successful password update you will be redirected to login page where you should login with new password
+        -if @user.errors.any?
+          .alert-message.block-message.error
+            %ul
+              - @user.errors.full_messages.each do |msg|
+                %li= msg
+
+        .clearfix
+          = f.label :password
+          .input= f.password_field :password
+        .clearfix
+          = f.label :password_confirmation
+          .input= f.password_field :password_confirmation
 
-    .clearfix
-      = f.label :password
-      .input= f.password_field :password
-    .clearfix
-      = f.label :password_confirmation
-      .input= f.password_field :password_confirmation
+    - if Settings.omniauth.enabled
+      .span5.right
+        .auth_methods.alert.alert-info
+          %strong Tip: Use one of the following sites to login
+          %ul
+            - User.omniauth_providers.each do |provider|
+              %li= link_to authbutton(provider), |
+                   omniauth_authorize_path(User, provider) |
   .actions
     = f.submit 'Save', class: "btn primary"
index 95cce2b..4d89cd3 100644 (file)
         %strong Tip:
         You can change your avatar at gravatar.com
 
+      - if Settings.omniauth.enabled && @user.provider?
+        %h4
+          Omniauth Providers:
+        = link_to "Change", profile_password_path, class: "btn small right"
+        You can login through #{@user.provider.titleize}!
+        = authbutton(@user.provider, 32)
+
       %h4
         Personal projects:
         %small.right
index 1818f2c..622ac9e 100644 (file)
@@ -1,4 +1,4 @@
-# # # # # # # # # # # # # # # # # # 
+# # # # # # # # # # # # # # # # # #
 # Gitlab application config file  #
 # # # # # # # # # # # # # # # # # #
 
@@ -19,14 +19,14 @@ email:
 
 # Application specific settings
 # Like default project limit for user etc
-app: 
-  default_projects_limit: 10 
+app:
+  default_projects_limit: 10
   # backup_path: "/vol/backups"   # default: Rails.root + backups/
   # backup_keep_time: 604800      # default: 0 (forever) (in seconds)
 
 
-# 
-# 2. Advanced settings: 
+#
+# 2. Advanced settings:
 # ==========================
 
 # Git Hosting configuration
@@ -49,3 +49,15 @@ git:
   git_max_size: 5242880 # 5.megabytes
   # Git timeout to read commit, in seconds
   git_timeout: 10
+
+# Omniauth configuration
+# omniauth:
+#   enabled: true
+#   providers:
+#     - { name: 'google_oauth2', app_id: 'YOUR APP ID',
+#         app_secret: 'YOUR APP SECRET',
+#         args: { access_type: 'offline', approval_prompt: '' } }
+#     - { name: 'twitter', app_id: 'YOUR APP ID',
+#         app_secret: 'YOUR APP SECRET'}
+#     - { name: 'github', app_id: 'YOUR APP ID',
+#         app_secret: 'YOUR APP SECRET' }
index 5c5987a..741a29d 100644 (file)
@@ -6,7 +6,7 @@ class Settings < Settingslogic
       self.web['protocol'] ||= web.https ? "https" : "http"
     end
 
-    def web_host 
+    def web_host
       self.web['host'] ||= 'localhost'
     end
 
@@ -14,11 +14,11 @@ class Settings < Settingslogic
       self.email['from'] ||= ("notify@" + web_host)
     end
 
-    def url 
+    def url
       self['url'] ||= build_url
-    end 
+    end
 
-    def web_port 
+    def web_port
       if web.https
         web['port'] = 443
       else
@@ -36,7 +36,7 @@ class Settings < Settingslogic
       raw_url << web_host
 
       if web_custom_port?
-        raw_url << ":#{web_port}" 
+        raw_url << ":#{web_port}"
       end
 
       raw_url
@@ -111,5 +111,14 @@ class Settings < Settingslogic
     def backup_keep_time
       app['backup_keep_time'] || 0
     end
+
+    def omniauth_enabled?
+      omniauth['enabled'] || false
+    end
+
+    def omniauth_providers
+      omniauth['providers'] || []
+    end
+
   end
 end
diff --git a/db/migrate/20120803152018_add_provider_and_uid_to_users.rb b/db/migrate/20120803152018_add_provider_and_uid_to_users.rb
new file mode 100644 (file)
index 0000000..14f53e4
--- /dev/null
@@ -0,0 +1,6 @@
+class AddProviderAndUidToUsers < ActiveRecord::Migration
+  def change
+    add_column :users, :provider, :string
+    add_column :users, :uid, :string
+  end
+end
index c4c54f5..5ac159d 100644 (file)
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20120712080407) do
+ActiveRecord::Schema.define(:version => 20120803152018) do
 
   create_table "events", :force => true do |t|
     t.string   "target_type"
@@ -146,31 +146,33 @@ ActiveRecord::Schema.define(:version => 20120712080407) do
   end
 
   create_table "users", :force => true do |t|
-    t.string   "email",                                 :default => "",    :null => false
-    t.string   "encrypted_password",     :limit => 128, :default => "",    :null => false
+    t.string   "email",                  :default => "",    :null => false
+    t.string   "encrypted_password",     :default => "",    :null => false
     t.string   "reset_password_token"
     t.datetime "reset_password_sent_at"
     t.datetime "remember_created_at"
-    t.integer  "sign_in_count",                         :default => 0
+    t.integer  "sign_in_count",          :default => 0
     t.datetime "current_sign_in_at"
     t.datetime "last_sign_in_at"
     t.string   "current_sign_in_ip"
     t.string   "last_sign_in_ip"
-    t.datetime "created_at",                                               :null => false
-    t.datetime "updated_at",                                               :null => false
+    t.datetime "created_at",                                :null => false
+    t.datetime "updated_at",                                :null => false
     t.string   "name"
-    t.boolean  "admin",                                 :default => false, :null => false
-    t.integer  "projects_limit",                        :default => 10
-    t.string   "skype",                                 :default => "",    :null => false
-    t.string   "linkedin",                              :default => "",    :null => false
-    t.string   "twitter",                               :default => "",    :null => false
+    t.boolean  "admin",                  :default => false, :null => false
+    t.integer  "projects_limit",         :default => 10
+    t.string   "skype",                  :default => "",    :null => false
+    t.string   "linkedin",               :default => "",    :null => false
+    t.string   "twitter",                :default => "",    :null => false
     t.string   "authentication_token"
-    t.boolean  "dark_scheme",                           :default => false, :null => false
-    t.integer  "theme_id",                              :default => 1,     :null => false
+    t.boolean  "dark_scheme",            :default => false, :null => false
+    t.integer  "theme_id",               :default => 1,     :null => false
     t.string   "bio"
-    t.boolean  "blocked",                               :default => false, :null => false
-    t.integer  "failed_attempts",                       :default => 0
+    t.boolean  "blocked",                :default => false, :null => false
+    t.integer  "failed_attempts",        :default => 0
     t.datetime "locked_at"
+    t.string   "provider"
+    t.string   "uid"
   end
 
   add_index "users", ["email"], :name => "index_users_on_email", :unique => true
diff --git a/vendor/assets/images/authbuttons/github_32.png b/vendor/assets/images/authbuttons/github_32.png
new file mode 100644 (file)
index 0000000..247e52a
Binary files /dev/null and b/vendor/assets/images/authbuttons/github_32.png differ
diff --git a/vendor/assets/images/authbuttons/github_64.png b/vendor/assets/images/authbuttons/github_64.png
new file mode 100644 (file)
index 0000000..fca7bf4
Binary files /dev/null and b/vendor/assets/images/authbuttons/github_64.png differ
diff --git a/vendor/assets/images/authbuttons/google_32.png b/vendor/assets/images/authbuttons/google_32.png
new file mode 100644 (file)
index 0000000..3909e9d
Binary files /dev/null and b/vendor/assets/images/authbuttons/google_32.png differ
diff --git a/vendor/assets/images/authbuttons/google_64.png b/vendor/assets/images/authbuttons/google_64.png
new file mode 100644 (file)
index 0000000..e55f34f
Binary files /dev/null and b/vendor/assets/images/authbuttons/google_64.png differ
diff --git a/vendor/assets/images/authbuttons/twitter_32.png b/vendor/assets/images/authbuttons/twitter_32.png
new file mode 100644 (file)
index 0000000..daadcff
Binary files /dev/null and b/vendor/assets/images/authbuttons/twitter_32.png differ
diff --git a/vendor/assets/images/authbuttons/twitter_64.png b/vendor/assets/images/authbuttons/twitter_64.png
new file mode 100644 (file)
index 0000000..68b7453
Binary files /dev/null and b/vendor/assets/images/authbuttons/twitter_64.png differ