Commit 621affecb59b8ce5304370cfd7979fba2b73ff4e

Authored by Dmitriy Zaporozhets
2 parents 40eec08c 0dd94cd8

Merge branch 'master' of https://github.com/funglaub/gitlabhq into funglaub-master

Conflicts:
	Gemfile.lock
	app/helpers/application_helper.rb
	app/views/devise/sessions/new.html.erb
	db/schema.rb
Gemfile
... ... @@ -16,6 +16,10 @@ gem "mysql2"
16 16  
17 17 # Auth
18 18 gem "devise", "~> 2.1.0"
  19 +gem 'omniauth'
  20 +gem 'omniauth-google-oauth2'
  21 +gem 'omniauth-twitter'
  22 +gem 'omniauth-github'
19 23  
20 24 # GITLAB patched libs
21 25 gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
... ...
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
... ... @@ -134,7 +134,7 @@ $hover: #fdf5d9;
134 134 * TODO: clean it
135 135 */
136 136 @import "common.scss";
137   -
  137 +@import "auth_methods.scss";
138 138  
139 139 /**
140 140 * Styles related to specific part of app
... ...
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 @user = User.find_for_ldap_auth(request.env["omniauth.auth"], current_user)
... ... @@ -19,4 +19,33 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
19 19 sign_in_and_redirect @user
20 20 end
21 21  
  22 + Settings.omniauth_providers.each do |provider|
  23 + define_method provider['name'] do
  24 + handle_omniauth
  25 + end
  26 + end
  27 +
  28 + private
  29 +
  30 + def handle_omniauth
  31 + oauth = request.env['omniauth.auth']
  32 + provider, uid = oauth['provider'], oauth['uid']
  33 +
  34 + if current_user
  35 + # Change a logged-in user's authentication method:
  36 + current_user.extern_uid = uid
  37 + current_user.provider = provider
  38 + current_user.save
  39 + redirect_to profile_path
  40 + else
  41 + @user = User.find_or_new_for_omniauth(oauth)
  42 +
  43 + if @user
  44 + sign_in_and_redirect @user
  45 + else
  46 + flash[:notice] = "There's no such user!"
  47 + redirect_to new_user_session_path
  48 + end
  49 + end
  50 + end
22 51 end
... ...
app/helpers/application_helper.rb
... ... @@ -135,4 +135,9 @@ module ApplicationHelper
135 135 "Never"
136 136 end
137 137 end
  138 +
  139 + def authbutton(provider, size = 64)
  140 + image_tag("authbuttons/#{provider.to_s.split('_').first}_#{size}.png",
  141 + alt: "Sign in with #{provider.to_s.titleize}" )
  142 + end
138 143 end
... ...
app/models/user.rb
... ... @@ -86,10 +86,50 @@ class User < ActiveRecord::Base
86 86 where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
87 87 end
88 88  
  89 + def self.create_from_omniauth(auth, ldap = false)
  90 + provider, uid = auth.provider, auth.uid
  91 + name = auth.info.name.force_encoding("utf-8")
  92 + email = auth.info.email.downcase unless auth.info.email.nil?
  93 +
  94 + ldap_prefix = ldap ? '(LDAP) ' : ''
  95 + raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
  96 + " address" if auth.info.email.blank?
  97 +
  98 + logger.info "#{ldap_prefix}Creating user from #{provider} login"\
  99 + " {uid => #{uid}, name => #{name}, email => #{email}}"
  100 + password = Devise.friendly_token[0, 8].downcase
  101 + @user = User.new(
  102 + extern_uid: uid,
  103 + provider: provider,
  104 + name: name,
  105 + email: email,
  106 + password: password,
  107 + password_confirmation: password,
  108 + projects_limit: Gitlab.config.default_projects_limit,
  109 + )
  110 + if Gitlab.config.omniauth.block_auto_created_users && !ldap
  111 + @user.blocked = true
  112 + end
  113 + @user.save!
  114 + @user
  115 + end
  116 +
  117 + def self.find_or_new_for_omniauth(auth)
  118 + provider, uid = auth.provider, auth.uid
  119 +
  120 + if @user = User.find_by_provider_and_extern_uid(provider, uid)
  121 + @user
  122 + else
  123 + if Gitlab.config.omniauth.allow_single_sign_on
  124 + @user = User.create_from_omniauth(auth)
  125 + @user
  126 + end
  127 + end
  128 + end
  129 +
89 130 def self.find_for_ldap_auth(auth, signed_in_resource=nil)
90 131 uid = auth.info.uid
91 132 provider = auth.provider
92   - name = auth.info.name.force_encoding("utf-8")
93 133 email = auth.info.email.downcase unless auth.info.email.nil?
94 134 raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
95 135  
... ... @@ -101,17 +141,7 @@ class User < ActiveRecord::Base
101 141 @user.update_attributes(:extern_uid => uid, :provider => provider)
102 142 @user
103 143 else
104   - logger.info "Creating user from LDAP login {uid => #{uid}, name => #{name}, email => #{email}}"
105   - password = Devise.friendly_token[0, 8].downcase
106   - @user = User.create(
107   - :extern_uid => uid,
108   - :provider => provider,
109   - :name => name,
110   - :email => email,
111   - :password => password,
112   - :password_confirmation => password,
113   - :projects_limit => Gitlab.config.default_projects_limit
114   - )
  144 + create_from_omniauth(auth)
115 145 end
116 146 end
117 147  
... ... @@ -148,4 +178,3 @@ end
148 178 # bio :string(255)
149 179 # blocked :boolean(1) default(FALSE), not null
150 180 #
151   -
... ...
app/views/devise/sessions/new.html.erb 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +<% unless ldap_enable? -%>
  2 +
  3 + <%= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f| %>
  4 + <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %>
  5 +
  6 + <%= f.text_field :email, :class => "text top", :placeholder => "Email" %>
  7 + <%= f.password_field :password, :class => "text bottom", :placeholder => "Password" %>
  8 +
  9 + <% if devise_mapping.rememberable? -%>
  10 + <div class="clearfix inputs-list"> <label class="checkbox remember_me" for="user_remember_me"><%= f.check_box :remember_me %><span>Remember me</span></label></div>
  11 + <% end -%>
  12 + <br/>
  13 + <%= f.submit "Sign in", :class => "primary btn" %>
  14 + <div class="right"> <%= render :partial => "devise/shared/links" %></div>
  15 +
  16 + <%- if devise_mapping.omniauthable? %>
  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>
  26 + <% end -%>
  27 +
  28 + <% end %>
  29 +
  30 +<% else %>
  31 + <%= render :partial => 'devise/sessions/new_ldap' %>
  32 +<% 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 save-btn"
... ...
app/views/profile/show.html.haml
... ... @@ -50,6 +50,13 @@
50 50 %strong Tip:
51 51 You can change your avatar at gravatar.com
52 52  
  53 + - if Settings.omniauth.enabled && @user.provider?
  54 + %h4
  55 + Omniauth Providers:
  56 + = link_to "Change", profile_password_path, class: "btn small right"
  57 + You can login through #{@user.provider.titleize}!
  58 + = authbutton(@user.provider, 32)
  59 +
53 60 %h4
54 61 Personal projects:
55 62 %small.right
... ...
config/gitlab.yml.example
... ... @@ -50,3 +50,21 @@ git:
50 50 git_max_size: 5242880 # 5.megabytes
51 51 # Git timeout to read commit, in seconds
52 52 git_timeout: 10
  53 +
  54 +# Omniauth configuration
  55 +omniauth:
  56 + enabled: false
  57 + providers:
  58 + allow_single_sign_on: false
  59 + block_auto_created_users: true
  60 +
  61 +# omniauth:
  62 +# enabled: true
  63 +# providers:
  64 +# - { name: 'google_oauth2', app_id: 'YOUR APP ID',
  65 +# app_secret: 'YOUR APP SECRET',
  66 +# args: { access_type: 'offline', approval_prompt: '' } }
  67 +# - { name: 'twitter', app_id: 'YOUR APP ID',
  68 +# app_secret: 'YOUR APP SECRET'}
  69 +# - { name: 'github', app_id: 'YOUR APP ID',
  70 +# 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
... ... @@ -120,6 +120,14 @@ class Settings &lt; Settingslogic
120 120 app['backup_keep_time'] || 0
121 121 end
122 122  
  123 + def omniauth_enabled?
  124 + omniauth['enabled'] || false
  125 + end
  126 +
  127 + def omniauth_providers
  128 + omniauth['providers'] || []
  129 + end
  130 +
123 131 def disable_gravatar?
124 132 app['disable_gravatar'] || false
125 133 end
... ...
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