Commit a64aff2f1c1ddc77b00211489d74fbc23c0c2fa2

Authored by Florian Unglaub
1 parent 4ce034ca

Omniauth Support

Gemfile
... ... @@ -8,6 +8,10 @@ gem "mysql2"
8 8  
9 9 # Auth
10 10 gem "devise", "~> 2.1.0"
  11 +gem 'omniauth'
  12 +gem 'omniauth-google-oauth2'
  13 +gem 'omniauth-twitter'
  14 +gem 'omniauth-github'
11 15  
12 16 # GITLAB patched libs
13 17 gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
... ...
Gemfile.lock
... ... @@ -166,6 +166,8 @@ GEM
166 166 eventmachine (0.12.10)
167 167 execjs (1.4.0)
168 168 multi_json (~> 1.0)
  169 + faraday (0.8.1)
  170 + multipart-post (~> 1.1)
169 171 ffaker (1.14.0)
170 172 ffi (1.0.11)
171 173 foreman (0.47.0)
... ... @@ -191,6 +193,7 @@ GEM
191 193 httparty (0.8.3)
192 194 multi_json (~> 1.0)
193 195 multi_xml
  196 + httpauth (0.1)
194 197 i18n (0.6.0)
195 198 journey (1.0.4)
196 199 jquery-rails (2.0.2)
... ... @@ -200,6 +203,8 @@ GEM
200 203 jquery-rails
201 204 railties (>= 3.1.0)
202 205 json (1.7.4)
  206 + jwt (0.1.5)
  207 + multi_json (>= 1.0)
203 208 kaminari (0.13.0)
204 209 actionpack (>= 3.0.0)
205 210 activesupport (>= 3.0.0)
... ... @@ -223,12 +228,35 @@ GEM
223 228 sprockets (~> 2.0)
224 229 multi_json (1.3.6)
225 230 multi_xml (0.5.1)
  231 + multipart-post (1.1.5)
226 232 mysql2 (0.3.11)
227 233 net-ldap (0.2.2)
228 234 nokogiri (1.5.3)
  235 + oauth (0.4.6)
  236 + oauth2 (0.8.0)
  237 + faraday (~> 0.8)
  238 + httpauth (~> 0.1)
  239 + jwt (~> 0.1.4)
  240 + multi_json (~> 1.0)
  241 + rack (~> 1.2)
229 242 omniauth (1.1.0)
230 243 hashie (~> 1.2)
231 244 rack
  245 + omniauth-github (1.0.1)
  246 + omniauth (~> 1.0)
  247 + omniauth-oauth2 (~> 1.0)
  248 + omniauth-google-oauth2 (0.1.13)
  249 + omniauth (~> 1.0)
  250 + omniauth-oauth2
  251 + omniauth-oauth (1.0.1)
  252 + oauth
  253 + omniauth (~> 1.0)
  254 + omniauth-oauth2 (1.1.0)
  255 + oauth2 (~> 0.8.0)
  256 + omniauth (~> 1.0)
  257 + omniauth-twitter (0.0.12)
  258 + multi_json (~> 1.3)
  259 + omniauth-oauth (~> 1.0)
232 260 orm_adapter (0.3.0)
233 261 polyglot (0.3.3)
234 262 posix-spawn (0.3.6)
... ... @@ -411,7 +439,11 @@ DEPENDENCIES
411 439 minitest (>= 2.10)
412 440 modernizr (= 2.5.3)
413 441 mysql2
  442 + omniauth
  443 + omniauth-github
  444 + omniauth-google-oauth2
414 445 omniauth-ldap!
  446 + omniauth-twitter
415 447 pry
416 448 pygments.rb!
417 449 rack-mini-profiler
... ...
app/assets/stylesheets/auth_methods.scss 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +.auth_methods {
  2 + &ul {
  3 + margin: 0;
  4 + text-align:center;
  5 + padding: 5px;
  6 + &li {
  7 + display: inline;
  8 + }
  9 + }
  10 +}
... ...
app/assets/stylesheets/main.scss
... ... @@ -3,8 +3,8 @@
3 3  
4 4 /** GITLAB colors **/
5 5 $text_color:#222;
6   -$lite_text_color: #666;
7   -$link_color:#2A79A3;
  6 +$lite_text_color: #666;
  7 +$link_color:#2A79A3;
8 8 $active_link_color:#2FA0BB;
9 9 $active_bg_color:#79C3E0;
10 10 $active_bd_color: #2FA0BB;
... ... @@ -31,7 +31,7 @@ $hover: #FDF5D9;
31 31 box-shadow: 0 0 3px #ddd;
32 32 }
33 33  
34   -@mixin solid_shade {
  34 +@mixin solid_shade {
35 35 -moz-box-shadow: 0 0 0 3px #eee;
36 36 -webkit-box-shadow: 0 0 0 3px #eee;
37 37 box-shadow: 0 0 0 3px #eee;
... ... @@ -73,21 +73,21 @@ $hover: #FDF5D9;
73 73  
74 74  
75 75 /**
76   - * Header of application.
  76 + * Header of application.
77 77 * Contain application logo, search panel, profile icon
78 78 */
79 79 @import "sections/header.scss";
80 80  
81 81 /**
82   - * Navigation menu of application.
  82 + * Navigation menu of application.
83 83 * Panel with links to pages depends on project, profile or admin area
84 84 */
85 85 @import "sections/nav.scss";
86 86  
87 87 /**
88   - * This file represent some UI that can be changed
89   - * during web app restyle or theme select.
90   - *
  88 + * This file represent some UI that can be changed
  89 + * during web app restyle or theme select.
  90 + *
91 91 * Next items should be placed there
92 92 * - link, button colors
93 93 * - header restyles
... ... @@ -118,11 +118,11 @@ $hover: #FDF5D9;
118 118 * Most of application styles placed here.
119 119 * This file represent common UI that should not be changed between themes
120 120 * or project restyling like form width or user avatar class or commit title
121   - *
  121 + *
122 122 * TODO: clean it
123 123 */
124 124 @import "common.scss";
125   -
  125 +@import "auth_methods.scss";
126 126  
127 127 /**
128 128 * Styles related to specific part of app
... ... @@ -140,17 +140,17 @@ $hover: #FDF5D9;
140 140 @import "ref_select.scss";
141 141  
142 142 /**
143   - * Code (files list) styles. Browsing project files there
  143 + * Code (files list) styles. Browsing project files there
144 144 */
145 145 @import "sections/tree.scss";
146 146  
147 147 /**
148   - * This file represent notes(comments) styles
  148 + * This file represent notes(comments) styles
149 149 */
150 150 @import "sections/notes.scss";
151 151  
152 152 /**
153   - * Devise styles
  153 + * Devise styles
154 154 */
155 155 @import "sections/login.scss";
156 156  
... ...
app/controllers/omniauth_callbacks_controller.rb
... ... @@ -9,7 +9,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
9 9 error ||= env["omniauth.error.type"].to_s
10 10 error.to_s.humanize if error
11 11 end
12   -
  12 +
13 13 def ldap
14 14 # We only find ourselves here if the authentication to LDAP was successful.
15 15 info = request.env["omniauth.auth"]["info"]
... ... @@ -20,4 +20,34 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
20 20 sign_in_and_redirect @user
21 21 end
22 22  
  23 + Settings.omniauth_providers.each do |provider|
  24 + define_method provider['name'] do
  25 + handle_omniauth
  26 + end
  27 + end
  28 +
  29 + private
  30 +
  31 + def handle_omniauth
  32 + oauth = request.env['omniauth.auth']
  33 + provider, uid = oauth['provider'], oauth['uid']
  34 +
  35 + if current_user
  36 + # Change a logged-in user's authentication method:
  37 + current_user.uid = uid
  38 + current_user.provider = provider
  39 + current_user.save
  40 + redirect_to profile_path
  41 + else
  42 + @user = User.find_by_provider_and_uid(provider, uid)
  43 +
  44 + if @user
  45 + sign_in_and_redirect @user
  46 + else
  47 + flash[:notice] = "There's no such user!"
  48 + redirect_to new_user_session_path
  49 + end
  50 + end
  51 + end
  52 +
23 53 end
... ...
app/helpers/application_helper.rb
... ... @@ -75,16 +75,16 @@ module ApplicationHelper
75 75 end
76 76  
77 77 def show_last_push_widget?(event)
78   - event &&
  78 + event &&
79 79 event.last_push_to_non_root? &&
80 80 !event.rm_ref? &&
81   - event.project &&
  81 + event.project &&
82 82 event.project.merge_requests_enabled
83 83 end
84 84  
85 85 def tab_class(tab_key)
86 86 active = case tab_key
87   -
  87 +
88 88 # Project Area
89 89 when :wall; wall_tab?
90 90 when :wiki; controller.controller_name == "wikis"
... ... @@ -123,4 +123,9 @@ module ApplicationHelper
123 123 def hexdigest(string)
124 124 Digest::SHA1.hexdigest string
125 125 end
  126 +
  127 + def authbutton(provider, size = 64)
  128 + image_tag("authbuttons/#{provider.to_s.split('_').first}_#{size}.png",
  129 + alt: "Sign in with #{provider.to_s.titleize}" )
  130 + end
126 131 end
... ...
app/views/devise/sessions/new.html.erb
... ... @@ -14,10 +14,15 @@
14 14 <div class="right"> <%= render :partial => "devise/shared/links" %></div>
15 15  
16 16 <%- if devise_mapping.omniauthable? %>
17   - <%- resource_class.omniauth_providers.each do |provider| %>
18   - <hr/>
19   - <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary" %><br />
20   - <% end -%>
  17 + <hr/>
  18 + <div class="auth_methods">
  19 + <ul>
  20 + <%- resource_class.omniauth_providers.each do |provider| %>
  21 + <li><%= link_to authbutton(provider),
  22 + omniauth_authorize_path(resource_name, provider) %></li>
  23 + <% end -%>
  24 + </ul>
  25 + </div>
21 26 <% end -%>
22 27  
23 28 <% end %>
... ...
app/views/layouts/profile.html.haml
... ... @@ -10,7 +10,7 @@
10 10 = link_to "Profile", profile_path
11 11  
12 12 %li{class: tab_class(:password)}
13   - = link_to "Password", profile_password_path
  13 + = link_to "Authentication", profile_password_path
14 14  
15 15 %li{class: tab_class(:ssh_keys)}
16 16 = link_to keys_path do
... ...
app/views/profile/password.html.haml
1 1 %h3.page_title Password
2 2 %hr
  3 +
3 4 = form_for @user, url: profile_password_path, method: :put do |f|
4   - .data
5   - %p.slead After successful password update you will be redirected to login page where you should login with new password
6   - -if @user.errors.any?
7   - .alert-message.block-message.error
8   - %ul
9   - - @user.errors.full_messages.each do |msg|
10   - %li= msg
  5 + .row
  6 + .span7
  7 + .data
  8 + %p.slead After successful password update you will be redirected to login page where you should login with new password
  9 + -if @user.errors.any?
  10 + .alert-message.block-message.error
  11 + %ul
  12 + - @user.errors.full_messages.each do |msg|
  13 + %li= msg
  14 +
  15 + .clearfix
  16 + = f.label :password
  17 + .input= f.password_field :password
  18 + .clearfix
  19 + = f.label :password_confirmation
  20 + .input= f.password_field :password_confirmation
11 21  
12   - .clearfix
13   - = f.label :password
14   - .input= f.password_field :password
15   - .clearfix
16   - = f.label :password_confirmation
17   - .input= f.password_field :password_confirmation
  22 + - if Settings.omniauth.enabled
  23 + .span5.right
  24 + .auth_methods.alert.alert-info
  25 + %strong Tip: Use one of the following sites to login
  26 + %ul
  27 + - User.omniauth_providers.each do |provider|
  28 + %li= link_to authbutton(provider), |
  29 + omniauth_authorize_path(User, provider) |
18 30 .actions
19 31 = f.submit 'Save', class: "btn primary"
... ...
app/views/profile/show.html.haml
... ... @@ -49,6 +49,13 @@
49 49 %strong Tip:
50 50 You can change your avatar at gravatar.com
51 51  
  52 + - if Settings.omniauth.enabled && @user.provider?
  53 + %h4
  54 + Omniauth Providers:
  55 + = link_to "Change", profile_password_path, class: "btn small right"
  56 + You can login through #{@user.provider.titleize}!
  57 + = authbutton(@user.provider, 32)
  58 +
52 59 %h4
53 60 Personal projects:
54 61 %small.right
... ...
config/gitlab.yml.example
1   -# # # # # # # # # # # # # # # # # #
  1 +# # # # # # # # # # # # # # # # # #
2 2 # Gitlab application config file #
3 3 # # # # # # # # # # # # # # # # # #
4 4  
... ... @@ -19,14 +19,14 @@ email:
19 19  
20 20 # Application specific settings
21 21 # Like default project limit for user etc
22   -app:
23   - default_projects_limit: 10
  22 +app:
  23 + default_projects_limit: 10
24 24 # backup_path: "/vol/backups" # default: Rails.root + backups/
25 25 # backup_keep_time: 604800 # default: 0 (forever) (in seconds)
26 26  
27 27  
28   -#
29   -# 2. Advanced settings:
  28 +#
  29 +# 2. Advanced settings:
30 30 # ==========================
31 31  
32 32 # Git Hosting configuration
... ... @@ -49,3 +49,15 @@ git:
49 49 git_max_size: 5242880 # 5.megabytes
50 50 # Git timeout to read commit, in seconds
51 51 git_timeout: 10
  52 +
  53 +# Omniauth configuration
  54 +# omniauth:
  55 +# enabled: true
  56 +# providers:
  57 +# - { name: 'google_oauth2', app_id: 'YOUR APP ID',
  58 +# app_secret: 'YOUR APP SECRET',
  59 +# args: { access_type: 'offline', approval_prompt: '' } }
  60 +# - { name: 'twitter', app_id: 'YOUR APP ID',
  61 +# app_secret: 'YOUR APP SECRET'}
  62 +# - { name: 'github', app_id: 'YOUR APP ID',
  63 +# app_secret: 'YOUR APP SECRET' }
... ...
config/initializers/1_settings.rb
... ... @@ -6,7 +6,7 @@ class Settings &lt; Settingslogic
6 6 self.web['protocol'] ||= web.https ? "https" : "http"
7 7 end
8 8  
9   - def web_host
  9 + def web_host
10 10 self.web['host'] ||= 'localhost'
11 11 end
12 12  
... ... @@ -14,11 +14,11 @@ class Settings &lt; Settingslogic
14 14 self.email['from'] ||= ("notify@" + web_host)
15 15 end
16 16  
17   - def url
  17 + def url
18 18 self['url'] ||= build_url
19   - end
  19 + end
20 20  
21   - def web_port
  21 + def web_port
22 22 if web.https
23 23 web['port'] = 443
24 24 else
... ... @@ -36,7 +36,7 @@ class Settings &lt; Settingslogic
36 36 raw_url << web_host
37 37  
38 38 if web_custom_port?
39   - raw_url << ":#{web_port}"
  39 + raw_url << ":#{web_port}"
40 40 end
41 41  
42 42 raw_url
... ... @@ -111,5 +111,14 @@ class Settings &lt; Settingslogic
111 111 def backup_keep_time
112 112 app['backup_keep_time'] || 0
113 113 end
  114 +
  115 + def omniauth_enabled?
  116 + omniauth['enabled'] || false
  117 + end
  118 +
  119 + def omniauth_providers
  120 + omniauth['providers'] || []
  121 + end
  122 +
114 123 end
115 124 end
... ...
db/migrate/20120803152018_add_provider_and_uid_to_users.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +class AddProviderAndUidToUsers < ActiveRecord::Migration
  2 + def change
  3 + add_column :users, :provider, :string
  4 + add_column :users, :uid, :string
  5 + end
  6 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20120712080407) do
  14 +ActiveRecord::Schema.define(:version => 20120803152018) do
15 15  
16 16 create_table "events", :force => true do |t|
17 17 t.string "target_type"
... ... @@ -146,31 +146,33 @@ ActiveRecord::Schema.define(:version =&gt; 20120712080407) do
146 146 end
147 147  
148 148 create_table "users", :force => true do |t|
149   - t.string "email", :default => "", :null => false
150   - t.string "encrypted_password", :limit => 128, :default => "", :null => false
  149 + t.string "email", :default => "", :null => false
  150 + t.string "encrypted_password", :default => "", :null => false
151 151 t.string "reset_password_token"
152 152 t.datetime "reset_password_sent_at"
153 153 t.datetime "remember_created_at"
154   - t.integer "sign_in_count", :default => 0
  154 + t.integer "sign_in_count", :default => 0
155 155 t.datetime "current_sign_in_at"
156 156 t.datetime "last_sign_in_at"
157 157 t.string "current_sign_in_ip"
158 158 t.string "last_sign_in_ip"
159   - t.datetime "created_at", :null => false
160   - t.datetime "updated_at", :null => false
  159 + t.datetime "created_at", :null => false
  160 + t.datetime "updated_at", :null => false
161 161 t.string "name"
162   - t.boolean "admin", :default => false, :null => false
163   - t.integer "projects_limit", :default => 10
164   - t.string "skype", :default => "", :null => false
165   - t.string "linkedin", :default => "", :null => false
166   - t.string "twitter", :default => "", :null => false
  162 + t.boolean "admin", :default => false, :null => false
  163 + t.integer "projects_limit", :default => 10
  164 + t.string "skype", :default => "", :null => false
  165 + t.string "linkedin", :default => "", :null => false
  166 + t.string "twitter", :default => "", :null => false
167 167 t.string "authentication_token"
168   - t.boolean "dark_scheme", :default => false, :null => false
169   - t.integer "theme_id", :default => 1, :null => false
  168 + t.boolean "dark_scheme", :default => false, :null => false
  169 + t.integer "theme_id", :default => 1, :null => false
170 170 t.string "bio"
171   - t.boolean "blocked", :default => false, :null => false
172   - t.integer "failed_attempts", :default => 0
  171 + t.boolean "blocked", :default => false, :null => false
  172 + t.integer "failed_attempts", :default => 0
173 173 t.datetime "locked_at"
  174 + t.string "provider"
  175 + t.string "uid"
174 176 end
175 177  
176 178 add_index "users", ["email"], :name => "index_users_on_email", :unique => true
... ...
vendor/assets/images/authbuttons/github_32.png 0 → 100644

1.89 KB

vendor/assets/images/authbuttons/github_64.png 0 → 100644

4.34 KB

vendor/assets/images/authbuttons/google_32.png 0 → 100644

1.58 KB

vendor/assets/images/authbuttons/google_64.png 0 → 100644

3.37 KB

vendor/assets/images/authbuttons/twitter_32.png 0 → 100644

1.41 KB

vendor/assets/images/authbuttons/twitter_64.png 0 → 100644

3.3 KB