1 commit 936a14e225037aca4cdeac11c843c7985e636c88
2 Author: Ismaƫl Bouya <ismael.bouya@normalesup.org>
3 Date: Mon Jul 24 19:58:24 2017 +0200
7 diff --git a/Gemfile b/Gemfile
8 index 414b0138d..2a934e9c9 100644
11 @@ -217,6 +217,9 @@ gem "thor", "0.19.1"
13 # gem "therubyracer", :platform => :ruby
16 +gem 'net-ldap', '~> 0.16'
18 group :production do # we don"t install these on travis to speed up test runs
21 diff --git a/Gemfile.lock b/Gemfile.lock
22 index 84f8172e4..cdbf19fcd 100644
23 --- a/Gemfile.lock 2019-01-13 19:55:52.538561762 +0100
24 +++ b/Gemfile.lock 2019-01-13 19:58:11.087099067 +0100
32 mini_portile2 (~> 2.3.0)
40 omniauth-tumblr (= 1.2)
41 diff --git a/app/models/user.rb b/app/models/user.rb
42 index 940a48f25..d1e2beeee 100644
43 --- a/app/models/user.rb
44 +++ b/app/models/user.rb
45 @@ -337,6 +337,12 @@ class User < ActiveRecord::Base
48 def send_confirm_email
49 + if skip_email_confirmation?
50 + self.email = unconfirmed_email
51 + self.unconfirmed_email = nil
55 return if unconfirmed_email.blank?
56 Workers::Mail::ConfirmEmail.perform_async(id)
58 @@ -554,6 +560,14 @@ class User < ActiveRecord::Base
63 + AppConfig.ldap.enable? && ldap_dn.present?
66 + def skip_email_confirmation?
67 + ldap_user? && AppConfig.ldap.skip_email_confirmation?
73 diff --git a/config/defaults.yml b/config/defaults.yml
74 index c046aff07..66e9afa13 100644
75 --- a/config/defaults.yml
76 +++ b/config/defaults.yml
77 @@ -202,6 +202,20 @@ defaults:
79 include_user_tags: false
86 + mail_attribute: mail
87 + skip_email_confirmation: true
89 + bind_dn: "cn=diaspora,dc=example,dc=com"
91 + search_base: "dc=example,dc=com"
92 + search_filter: "uid=%{username}"
93 + bind_template: "uid=%{username},dc=example,dc=com"
98 diff --git a/config/diaspora.yml.example b/config/diaspora.yml.example
99 index b2573625d..c357c8651 100644
100 --- a/config/diaspora.yml.example
101 +++ b/config/diaspora.yml.example
102 @@ -710,6 +710,36 @@ configuration: ## Section
103 ## If scope is 'tags', a comma separated list of tags here can be set.
104 ## For example "linux,diaspora", to receive posts related to these tags
107 + # Uncomment next line if you want to use LDAP on your instance
111 + # Use only LDAP authentication (don't try other means)
113 + # LDAP attribute to find the user's e-mail. Necessary to create accounts
114 + # for not existing users
115 + mail_attribute: mail
116 + # Skip e-mail confirmation when creating an account via LDAP.
117 + skip_email_confirmation: true
118 + # ----- Using bind_dn and bind_pw
119 + # bind_dn and bind_pw may be used if the diaspora instance
120 + # should be able to connect to LDAP to find and search for users.
123 + bind_dn: "cn=diaspora,dc=example,dc=com"
124 + bind_pw: "password"
125 + search_base: "dc=example,dc=com"
126 + # This is the filter with which to search for the user. %{username} will
127 + # be replaced by the given login.
128 + search_filter: "uid=%{username}"
130 + # ----- Using template
131 + # This setting doesn't require a diaspora LDAP user. Use a template, and
132 + # diaspora will try to login with the templated dn and password
134 + # bind_template: "uid=%{username},dc=example,dc=com"
137 ## Here you can override settings defined above if you need
138 ## to have them different in different environments.
139 diff --git a/config/initializers/0_ldap_authenticatable.rb b/config/initializers/0_ldap_authenticatable.rb
141 index 000000000..49846502f
143 +++ b/config/initializers/0_ldap_authenticatable.rb
146 +require 'devise/strategies/authenticatable'
150 + class LdapAuthenticatable < Authenticatable
152 + AppConfig.ldap.enable? && params[:user].present?
156 + ldap = Net::LDAP.new(
157 + host: AppConfig.ldap.host,
158 + port: AppConfig.ldap.port,
159 + encryption: :simple_tls,
162 + if AppConfig.ldap.use_bind_dn?
163 + ldap.auth AppConfig.ldap.bind_dn, AppConfig.ldap.bind_pw
166 + return fail(:ldap_configuration_error)
169 + search_filter = AppConfig.ldap.search_filter % { username: params[:user][:username] }
171 + result = ldap.search(base: AppConfig.ldap.search_base, filter: search_filter, result_set: true)
173 + if result.count != 1
177 + user_dn = result.first.dn
178 + user_email = result.first[AppConfig.ldap.mail_attribute].first
180 + user_dn = AppConfig.ldap.bind_template % { username: params[:user][:username] }
183 + ldap.auth user_dn, params[:user][:password]
186 + user = User.find_by(ldap_dn: user_dn)
188 + # We don't want to trust too much the email attribute from
189 + # LDAP: if the user can edit it himself, he may login as
192 + if !AppConfig.ldap.use_bind_dn?
193 + result = ldap.search(base: user_dn, scope: Net::LDAP::SearchScope_BaseObject, filter: "(objectClass=*)", result_set: true)
194 + user_email = result.first[AppConfig.ldap.mail_attribute].first
197 + if user_email.present? && User.find_by(email: user_email).nil?
198 + # Password is used for remember_me token
199 + user = User.build(email: user_email, ldap_dn: user_dn, password: SecureRandom.hex, username: params[:user][:username])
202 + elsif User.find_by(email: user_email).present?
203 + return fail(:ldap_existing_email)
205 + return fail(:ldap_cannot_create_account_without_email)
216 + if AppConfig.ldap.only_ldap?
217 + return fail(:ldap_invalid_login)
226 +Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable)
227 diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
228 index 3698e2373..14e88063e 100644
229 --- a/config/initializers/devise.rb
230 +++ b/config/initializers/devise.rb
231 @@ -250,10 +250,9 @@ Devise.setup do |config|
232 # If you want to use other strategies, that are not supported by Devise, or
233 # change the failure app, you can configure them inside the config.warden block.
235 - # config.warden do |manager|
236 - # manager.intercept_401 = false
237 - # manager.default_strategies(:scope => :user).unshift :some_external_strategy
239 + config.warden do |manager|
240 + manager.default_strategies(scope: :user).unshift :ldap_authenticatable
243 # ==> Mountable engine configurations
244 # When using Devise inside an engine, let's call it `MyEngine`, and this engine
245 diff --git a/db/migrate/20170724182100_add_ldap_dn_to_users.rb b/db/migrate/20170724182100_add_ldap_dn_to_users.rb
247 index 000000000..f5cc84d11
249 +++ b/db/migrate/20170724182100_add_ldap_dn_to_users.rb
251 +class AddLdapDnToUsers < ActiveRecord::Migration
253 + add_column :users, :ldap_dn, :text, null: true, default: nil
254 + add_index :users, ['ldap_dn'], :length => { "ldap_dn" => 191 }