devise_ldap_authenticatable 0.8.1 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -19
- data/lib/devise_ldap_authenticatable.rb +3 -1
- data/lib/devise_ldap_authenticatable/ldap/adapter.rb +2 -2
- data/lib/devise_ldap_authenticatable/ldap/connection.rb +28 -18
- data/lib/devise_ldap_authenticatable/model.rb +27 -23
- data/lib/devise_ldap_authenticatable/strategy.rb +24 -5
- data/lib/devise_ldap_authenticatable/version.rb +1 -1
- data/lib/generators/devise_ldap_authenticatable/install_generator.rb +14 -13
- data/lib/generators/devise_ldap_authenticatable/templates/ldap.yml +1 -0
- data/spec/rails_app/config/initializers/devise.rb +5 -0
- data/spec/rails_app/config/locales/devise.en.yml +1 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/unit/connection_spec.rb +14 -0
- data/spec/unit/user_spec.rb +46 -18
- metadata +105 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b851a53df509e6cf0d16292aa9192e06dfff3e7
|
4
|
+
data.tar.gz: 532280a974b9cf4bf52d34ff5a57b49cd33e6304
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dce1145454333fc039cab36e9c9c0c36178402fac1eff6f4d9bd552d3ac2eaa04fb8cf80e75750ed7c69e19fe93abe4a697288fb646f70481084114133c76725
|
7
|
+
data.tar.gz: c5084e9417909665e9aecb7591dad2fbaa42543498ad179a9ca7ce8fc75315c3c278c36ce5a4ddf74c7f202f64d34089bc17d828bff451e896ca116d5aa1338d
|
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
Devise LDAP Authenticatable
|
2
2
|
===========================
|
3
|
+
|
4
|
+
Why this fork?
|
5
|
+
--------------
|
6
|
+
This fork changes a few lines to allow the admin binding to be set to the user trying to log in.
|
7
|
+
|
3
8
|
[![Gem Version](https://badge.fury.io/rb/devise_ldap_authenticatable.png)](http://badge.fury.io/rb/devise_ldap_authenticatable)
|
4
9
|
[![Code Climate](https://codeclimate.com/github/cschiewek/devise_ldap_authenticatable.png)](https://codeclimate.com/github/cschiewek/devise_ldap_authenticatable)
|
5
10
|
[![Dependency Status](https://gemnasium.com/cschiewek/devise_ldap_authenticatable.png)](https://gemnasium.com/cschiewek/devise_ldap_authenticatable)
|
@@ -41,7 +46,7 @@ Run the rails generator for `devise_ldap_authenticatable`
|
|
41
46
|
|
42
47
|
rails generate devise_ldap_authenticatable:install [options]
|
43
48
|
|
44
|
-
This will install the
|
49
|
+
This will install the ldap.yml, update the devise.rb initializer, and update your user model. There are some options you can pass to it:
|
45
50
|
|
46
51
|
Options:
|
47
52
|
|
@@ -57,12 +62,10 @@ Querying LDAP
|
|
57
62
|
-------------
|
58
63
|
Given that `ldap_create_user` is set to true and you are authenticating with username, you can query an LDAP server for other attributes.
|
59
64
|
|
60
|
-
in your user model:
|
65
|
+
in your user model you have to simply define `ldap_before_save` method:
|
61
66
|
|
62
|
-
|
63
|
-
|
64
|
-
def get_ldap_email
|
65
|
-
self.email = Devise::LdapAdapter.get_ldap_param(self.username,"mail")
|
67
|
+
def ldap_before_save
|
68
|
+
self.email = Devise::LDAP::Adapter.get_ldap_param(self.username,"mail").first
|
66
69
|
end
|
67
70
|
|
68
71
|
Configuration
|
@@ -71,25 +74,20 @@ In initializer `config/initializers/devise.rb` :
|
|
71
74
|
|
72
75
|
* `ldap_logger` _(default: true)_
|
73
76
|
* If set to true, will log LDAP queries to the Rails logger.
|
74
|
-
|
75
77
|
* `ldap_create_user` _(default: false)_
|
76
|
-
* If set to true, all valid LDAP users will be allowed to login and an appropriate user record will be created.
|
77
|
-
If set to false, you will have to create the user record before they will be allowed to login.
|
78
|
-
|
78
|
+
* If set to true, all valid LDAP users will be allowed to login and an appropriate user record will be created. If set to false, you will have to create the user record before they will be allowed to login.
|
79
79
|
* `ldap_config` _(default: #{Rails.root}/config/ldap.yml)_
|
80
|
-
|
81
|
-
|
80
|
+
* Where to find the LDAP config file. Commented out to use the default, change if needed.
|
82
81
|
* `ldap_update_password` _(default: true)_
|
83
82
|
* When doing password resets, if true will update the LDAP server. Requires admin password in the ldap.yml
|
84
|
-
|
85
83
|
* `ldap_check_group_membership` _(default: false)_
|
86
84
|
* When set to true, the user trying to login will be checked to make sure they are in all of groups specified in the ldap.yml file.
|
87
|
-
|
88
85
|
* `ldap_check_attributes` _(default: false)_
|
89
86
|
* When set to true, the user trying to login will be checked to make sure they have all of the attributes in the ldap.yml file.
|
90
|
-
|
91
87
|
* `ldap_use_admin_to_bind` _(default: false)_
|
92
88
|
* When set to true, the admin user will be used to bind to the LDAP server during authentication.
|
89
|
+
* `ldap_check_group_membership_without_admin` _(default: false)_
|
90
|
+
* When set to true, the group membership check is done with the user's own credentials rather than with admin credentials. Since these credentials are only available to the Devise user model during the login flow, the group check function will not work if a group check is performed when this option is true outside of the login flow (e.g., before particular actions).
|
93
91
|
|
94
92
|
Advanced Configuration
|
95
93
|
----------------------
|
@@ -97,10 +95,12 @@ These parameters will be added to `config/initializers/devise.rb` when you pass
|
|
97
95
|
|
98
96
|
* `ldap_auth_username_builder` _(default: `Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }`)_
|
99
97
|
* You can pass a proc to the username option to explicitly specify the format that you search for a users' DN on your LDAP server.
|
98
|
+
* `ldap_auth_password_build` _(default: `Proc.new() {|new_password| Net::LDAP::Password.generate(:sha, new_password) }`)_
|
99
|
+
* Optionally you can define a proc to create custom password encrption when user reset password
|
100
100
|
|
101
101
|
Troubleshooting
|
102
102
|
--------------
|
103
|
-
**Using a "username" instead of an "email":** The field that is used for logins is the first key that's configured in the `config/devise.rb` file under `config.authentication_keys`, which by default is email. For help changing this, please see the [Railscast](http://railscasts.com/episodes/210-customizing-devise) that goes through how to customize Devise.
|
103
|
+
**Using a "username" instead of an "email":** The field that is used for logins is the first key that's configured in the `config/initializers/devise.rb` file under `config.authentication_keys`, which by default is email. For help changing this, please see the [Railscast](http://railscasts.com/episodes/210-customizing-devise) that goes through how to customize Devise. Also, this [documentation](https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-sign-in-using-their-username-or-email-address) from Devise can very helpful.
|
104
104
|
|
105
105
|
**SSL certificate invalid:** If you're using a test LDAP server running a self-signed SSL certificate, make sure the appropriate root certificate is installed on your system. Alternately, you may temporarily disable certificate checking for SSL by modifying your system LDAP configuration (e.g., `/etc/openldap/ldap.conf` or `/etc/ldap/ldap.conf`) to read `TLS_REQCERT never`.
|
106
106
|
|
@@ -111,11 +111,12 @@ For additional support, questions or discussions, please see the discussion foru
|
|
111
111
|
|
112
112
|
Development guide
|
113
113
|
------------
|
114
|
-
To contribute to `devise_ldap_authentication`, you should be able to run a test OpenLDAP server. Specifically, you need the `slapd`, `ldapadd`, and `ldapmodify` binaries.
|
115
114
|
|
116
|
-
|
115
|
+
Devise LDAP Authenticatable uses a running OpenLDAP server to do automated acceptance tests. You'll need the executables `slapd`, `ldapadd`, and `ldapmodify`.
|
116
|
+
|
117
|
+
On OS X, this is available out of the box.
|
117
118
|
|
118
|
-
On Ubuntu
|
119
|
+
On Ubuntu, you can install OpenLDAP with `sudo apt-get install slapd ldap-utils`. If slapd runs under AppArmor, add an exception like this to `/etc/apparmor.d/local/usr.sbin.slapd` to let slapd read our configs.
|
119
120
|
|
120
121
|
/path/to/devise_ldap_authenticatable/spec/ldap/** rw,$
|
121
122
|
|
@@ -16,6 +16,8 @@ module Devise
|
|
16
16
|
mattr_accessor :ldap_create_user
|
17
17
|
@@ldap_create_user = false
|
18
18
|
|
19
|
+
# A path to YAML config file or a Proc that returns a
|
20
|
+
# configuration hash
|
19
21
|
mattr_accessor :ldap_config
|
20
22
|
# @@ldap_config = "#{Rails.root}/config/ldap.yml"
|
21
23
|
|
@@ -44,4 +46,4 @@ Devise.add_module(:ldap_authenticatable,
|
|
44
46
|
:route => :session, ## This will add the routes, rather than in the routes.rb
|
45
47
|
:strategy => true,
|
46
48
|
:controller => :sessions,
|
47
|
-
:model => 'devise_ldap_authenticatable/model')
|
49
|
+
:model => 'devise_ldap_authenticatable/model')
|
@@ -26,7 +26,7 @@ module Devise
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.update_own_password(login, new_password, current_password)
|
29
|
-
set_ldap_param(login, :
|
29
|
+
set_ldap_param(login, :userPassword, ::Devise.ldap_auth_password_builder.call(new_password), current_password)
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.ldap_connect(login)
|
@@ -84,4 +84,4 @@ module Devise
|
|
84
84
|
|
85
85
|
end
|
86
86
|
|
87
|
-
end
|
87
|
+
end
|
@@ -4,7 +4,11 @@ module Devise
|
|
4
4
|
attr_reader :ldap, :login
|
5
5
|
|
6
6
|
def initialize(params = {})
|
7
|
-
|
7
|
+
if ::Devise.ldap_config.is_a?(Proc)
|
8
|
+
ldap_config = ::Devise.ldap_config.call
|
9
|
+
else
|
10
|
+
ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env]
|
11
|
+
end
|
8
12
|
ldap_options = params
|
9
13
|
ldap_config["ssl"] = :simple_tls if ldap_config["ssl"] === true
|
10
14
|
ldap_options[:encryption] = ldap_config["ssl"].to_sym if ldap_config["ssl"]
|
@@ -14,6 +18,8 @@ module Devise
|
|
14
18
|
@ldap.port = ldap_config["port"]
|
15
19
|
@ldap.base = ldap_config["base"]
|
16
20
|
@attribute = ldap_config["attribute"]
|
21
|
+
@allow_unauthenticated_bind = ldap_config["allow_unauthenticated_bind"]
|
22
|
+
|
17
23
|
@ldap_auth_username_builder = params[:ldap_auth_username_builder]
|
18
24
|
|
19
25
|
@group_base = ldap_config["group_base"]
|
@@ -22,6 +28,7 @@ module Devise
|
|
22
28
|
@required_attributes = ldap_config["require_attribute"]
|
23
29
|
|
24
30
|
@ldap.auth ldap_config["admin_user"], ldap_config["admin_password"] if params[:admin]
|
31
|
+
@ldap.auth params[:login], params[:password] if ldap_config["admin_as_user"]
|
25
32
|
|
26
33
|
@login = params[:login]
|
27
34
|
@password = params[:password]
|
@@ -37,19 +44,19 @@ module Devise
|
|
37
44
|
end
|
38
45
|
|
39
46
|
def dn
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
@dn ||= begin
|
48
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP dn lookup: #{@attribute}=#{@login}")
|
49
|
+
ldap_entry = search_for_login
|
50
|
+
if ldap_entry.nil?
|
51
|
+
@ldap_auth_username_builder.call(@attribute,@login,@ldap)
|
52
|
+
else
|
53
|
+
ldap_entry.dn
|
54
|
+
end
|
46
55
|
end
|
47
56
|
end
|
48
57
|
|
49
58
|
def ldap_param_value(param)
|
50
|
-
|
51
|
-
ldap_entry = nil
|
52
|
-
@ldap.search(:filter => filter) {|entry| ldap_entry = entry}
|
59
|
+
ldap_entry = search_for_login
|
53
60
|
|
54
61
|
if ldap_entry
|
55
62
|
unless ldap_entry[param].empty?
|
@@ -67,6 +74,7 @@ module Devise
|
|
67
74
|
end
|
68
75
|
|
69
76
|
def authenticate!
|
77
|
+
return false unless (@password.present? || @allow_unauthenticated_bind)
|
70
78
|
@ldap.auth(dn, @password)
|
71
79
|
@ldap.bind
|
72
80
|
end
|
@@ -174,13 +182,15 @@ module Devise
|
|
174
182
|
#
|
175
183
|
# @return [Object] the LDAP entry found; nil if not found
|
176
184
|
def search_for_login
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
185
|
+
@login_ldap_entry ||= begin
|
186
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP search for login: #{@attribute}=#{@login}")
|
187
|
+
filter = Net::LDAP::Filter.eq(@attribute.to_s, @login.to_s)
|
188
|
+
ldap_entry = nil
|
189
|
+
match_count = 0
|
190
|
+
@ldap.search(:filter => filter) {|entry| ldap_entry = entry; match_count+=1}
|
191
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP search yielded #{match_count} matches")
|
192
|
+
ldap_entry
|
193
|
+
end
|
184
194
|
end
|
185
195
|
|
186
196
|
private
|
@@ -223,4 +233,4 @@ module Devise
|
|
223
233
|
end
|
224
234
|
end
|
225
235
|
end
|
226
|
-
end
|
236
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'devise_ldap_authenticatable/strategy'
|
2
2
|
|
3
3
|
module Devise
|
4
4
|
module Models
|
@@ -18,7 +18,7 @@ module Devise
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def login_with
|
21
|
-
@login_with ||= Devise.mappings
|
21
|
+
@login_with ||= Devise.mappings.find {|k,v| v.class_name == self.class.name}.last.to.authentication_keys.first
|
22
22
|
self[@login_with]
|
23
23
|
end
|
24
24
|
|
@@ -45,11 +45,11 @@ module Devise
|
|
45
45
|
|
46
46
|
# Checks if a resource is valid upon authentication.
|
47
47
|
def valid_ldap_authentication?(password)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
Devise::LDAP::Adapter.valid_credentials?(login_with, password)
|
49
|
+
end
|
50
|
+
|
51
|
+
def ldap_entry
|
52
|
+
@ldap_entry ||= Devise::LDAP::Adapter.get_ldap_entry(login_with)
|
53
53
|
end
|
54
54
|
|
55
55
|
def ldap_groups
|
@@ -61,11 +61,15 @@ module Devise
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def ldap_dn
|
64
|
-
|
64
|
+
ldap_entry ? ldap_entry.dn : nil
|
65
65
|
end
|
66
66
|
|
67
|
-
def ldap_get_param(
|
68
|
-
|
67
|
+
def ldap_get_param(param)
|
68
|
+
if ldap_entry && !ldap_entry[param].empty?
|
69
|
+
value = ldap_entry.send(param)
|
70
|
+
else
|
71
|
+
nil
|
72
|
+
end
|
69
73
|
end
|
70
74
|
|
71
75
|
#
|
@@ -76,34 +80,34 @@ module Devise
|
|
76
80
|
# def ldap_before_save
|
77
81
|
# end
|
78
82
|
|
83
|
+
# Called after a successful LDAP authentication
|
84
|
+
def after_ldap_authentication
|
85
|
+
end
|
86
|
+
|
79
87
|
|
80
88
|
module ClassMethods
|
81
|
-
#
|
82
|
-
|
83
|
-
def authenticate_with_ldap(attributes={})
|
89
|
+
# Find a user for ldap authentication.
|
90
|
+
def find_for_ldap_authentication(attributes={})
|
84
91
|
auth_key = self.authentication_keys.first
|
85
92
|
return nil unless attributes[auth_key].present?
|
86
93
|
|
87
94
|
auth_key_value = (self.case_insensitive_keys || []).include?(auth_key) ? attributes[auth_key].downcase : attributes[auth_key]
|
95
|
+
auth_key_value = (self.strip_whitespace_keys || []).include?(auth_key) ? auth_key_value.strip : auth_key_value
|
88
96
|
|
89
|
-
# resource = find_for_ldap_authentication(conditions)
|
90
97
|
resource = where(auth_key => auth_key_value).first
|
91
98
|
|
92
|
-
if
|
99
|
+
if resource.blank?
|
93
100
|
resource = new
|
94
101
|
resource[auth_key] = auth_key_value
|
95
102
|
resource.password = attributes[:password]
|
96
103
|
end
|
97
104
|
|
98
|
-
if resource.
|
99
|
-
if resource.
|
100
|
-
|
101
|
-
resource.save!
|
102
|
-
end
|
103
|
-
return resource
|
104
|
-
else
|
105
|
-
return nil
|
105
|
+
if ::Devise.ldap_create_user && resource.new_record? && resource.valid_ldap_authentication?(attributes[:password])
|
106
|
+
resource.ldap_before_save if resource.respond_to?(:ldap_before_save)
|
107
|
+
resource.save!
|
106
108
|
end
|
109
|
+
|
110
|
+
resource
|
107
111
|
end
|
108
112
|
|
109
113
|
def update_with_password(resource)
|
@@ -3,16 +3,35 @@ require 'devise/strategies/authenticatable'
|
|
3
3
|
module Devise
|
4
4
|
module Strategies
|
5
5
|
class LdapAuthenticatable < Authenticatable
|
6
|
+
|
7
|
+
# Tests whether the returned resource exists in the database and the
|
8
|
+
# credentials are valid. If the resource is in the database and the credentials
|
9
|
+
# are valid, the user is authenticated. Otherwise failure messages are returned
|
10
|
+
# indicating whether the resource is not found in the database or the credentials
|
11
|
+
# are invalid.
|
6
12
|
def authenticate!
|
7
|
-
resource =
|
8
|
-
|
13
|
+
resource = mapping.to.find_for_ldap_authentication(authentication_hash.merge(password: password))
|
14
|
+
|
15
|
+
if resource.persisted?
|
16
|
+
if validate(resource) { resource.valid_ldap_authentication?(password) }
|
17
|
+
remember_me(resource)
|
18
|
+
resource.after_ldap_authentication
|
19
|
+
success!(resource)
|
20
|
+
else
|
21
|
+
return fail(:invalid) # Invalid credentials
|
22
|
+
end
|
23
|
+
end
|
9
24
|
|
10
|
-
if
|
11
|
-
|
25
|
+
if resource.new_record?
|
26
|
+
if validate(resource) { resource.valid_ldap_authentication?(password) }
|
27
|
+
return fail(:not_found_in_database) # Valid credentials
|
28
|
+
else
|
29
|
+
return fail(:invalid) # Invalid credentials
|
30
|
+
end
|
12
31
|
end
|
13
32
|
end
|
14
33
|
end
|
15
34
|
end
|
16
35
|
end
|
17
36
|
|
18
|
-
Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable)
|
37
|
+
Warden::Strategies.add(:ldap_authenticatable, Devise::Strategies::LdapAuthenticatable)
|
@@ -1,31 +1,31 @@
|
|
1
1
|
module DeviseLdapAuthenticatable
|
2
2
|
class InstallGenerator < Rails::Generators::Base
|
3
3
|
source_root File.expand_path("../templates", __FILE__)
|
4
|
-
|
4
|
+
|
5
5
|
class_option :user_model, :type => :string, :default => "user", :desc => "Model to update"
|
6
6
|
class_option :update_model, :type => :boolean, :default => true, :desc => "Update model to change from database_authenticatable to ldap_authenticatable"
|
7
7
|
class_option :add_rescue, :type => :boolean, :default => true, :desc => "Update Application Controller with resuce_from for DeviseLdapAuthenticatable::LdapException"
|
8
8
|
class_option :advanced, :type => :boolean, :desc => "Add advanced config options to the devise initializer"
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
|
11
11
|
def create_ldap_config
|
12
12
|
copy_file "ldap.yml", "config/ldap.yml"
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def create_default_devise_settings
|
16
16
|
inject_into_file "config/initializers/devise.rb", default_devise_settings, :after => "Devise.setup do |config|\n"
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def update_user_model
|
20
20
|
gsub_file "app/models/#{options.user_model}.rb", /:database_authenticatable/, ":ldap_authenticatable" if options.update_model?
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def update_application_controller
|
24
24
|
inject_into_class "app/controllers/application_controller.rb", ApplicationController, rescue_from_exception if options.add_rescue?
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
private
|
28
|
-
|
28
|
+
|
29
29
|
def default_devise_settings
|
30
30
|
settings = <<-eof
|
31
31
|
# ==> LDAP Configuration
|
@@ -34,22 +34,23 @@ module DeviseLdapAuthenticatable
|
|
34
34
|
# config.ldap_update_password = true
|
35
35
|
# config.ldap_config = "\#{Rails.root}/config/ldap.yml"
|
36
36
|
# config.ldap_check_group_membership = false
|
37
|
+
# config.ldap_check_group_membership_without_admin = false
|
37
38
|
# config.ldap_check_attributes = false
|
38
39
|
# config.ldap_use_admin_to_bind = false
|
39
40
|
# config.ldap_ad_group_check = false
|
40
|
-
|
41
|
+
|
41
42
|
eof
|
42
43
|
if options.advanced?
|
43
44
|
settings << <<-eof
|
44
45
|
# ==> Advanced LDAP Configuration
|
45
46
|
# config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "\#{attribute}=\#{login},\#{ldap.base}" }
|
46
|
-
|
47
|
+
|
47
48
|
eof
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
settings
|
51
52
|
end
|
52
|
-
|
53
|
+
|
53
54
|
def rescue_from_exception
|
54
55
|
<<-eof
|
55
56
|
rescue_from DeviseLdapAuthenticatable::LdapException do |exception|
|
@@ -57,6 +58,6 @@ module DeviseLdapAuthenticatable
|
|
57
58
|
end
|
58
59
|
eof
|
59
60
|
end
|
60
|
-
|
61
|
+
|
61
62
|
end
|
62
63
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
# You can also just copy and paste the tree (do not include the "authorizations") to each
|
4
4
|
# environment if you need something different per enviornment.
|
5
5
|
authorizations: &AUTHORIZATIONS
|
6
|
+
allow_unauthenticated_bind: false
|
6
7
|
group_base: ou=groups,dc=test,dc=com
|
7
8
|
## Requires config.ldap_check_group_membership in devise.rb be true
|
8
9
|
# Can have multiple values, must match all to be authorized
|
@@ -16,6 +16,11 @@ Devise.setup do |config|
|
|
16
16
|
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
|
17
17
|
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
|
18
18
|
|
19
|
+
|
20
|
+
if ::Devise.respond_to?(:secret_key)
|
21
|
+
::Devise.secret_key = '012a16191a7f61e84e55704e34b73db991a23ba396b6b7760596a3e80073e4464c55421c42a1a34327dee44828bec6745c48eba10cc0866799ec95c09ea27ada'
|
22
|
+
end
|
23
|
+
|
19
24
|
# Configure the class responsible to send e-mails.
|
20
25
|
# config.mailer = "Devise::Mailer"
|
21
26
|
|
@@ -17,6 +17,7 @@ en:
|
|
17
17
|
unauthenticated: 'You need to sign in or sign up before continuing.'
|
18
18
|
unconfirmed: 'You have to confirm your account before continuing.'
|
19
19
|
locked: 'Your account is locked.'
|
20
|
+
not_found_in_database: "Your account is not present in this application's database."
|
20
21
|
invalid: 'Invalid email or password.'
|
21
22
|
invalid_token: 'Invalid authentication token.'
|
22
23
|
timeout: 'Your session expired, please sign in again to continue.'
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,14 @@ require 'rspec/rails'
|
|
5
5
|
require 'rspec/autorun'
|
6
6
|
require 'factory_girl' # not sure why this is not already required
|
7
7
|
|
8
|
+
# Rails 4.1 and RSpec are a bit on different pages on who should run migrations
|
9
|
+
# on the test db and when.
|
10
|
+
#
|
11
|
+
# https://github.com/rspec/rspec-rails/issues/936
|
12
|
+
if defined?(ActiveRecord::Migration) && ActiveRecord::Migration.respond_to?(:maintain_test_schema!)
|
13
|
+
ActiveRecord::Migration.maintain_test_schema!
|
14
|
+
end
|
15
|
+
|
8
16
|
Dir[File.expand_path("support/**/*.rb", File.dirname(__FILE__))].each {|f| require f}
|
9
17
|
|
10
18
|
RSpec.configure do |config|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe 'Connection' do
|
4
|
+
it 'accepts a proc for ldap_config' do
|
5
|
+
::Devise.ldap_config = Proc.new() {{
|
6
|
+
'host' => 'localhost',
|
7
|
+
'port' => 3389,
|
8
|
+
'base' => 'ou=testbase,dc=test,dc=com',
|
9
|
+
'attribute' => 'cn',
|
10
|
+
}}
|
11
|
+
connection = Devise::LDAP::Connection.new()
|
12
|
+
expect(connection.ldap.base).to eq('ou=testbase,dc=test,dc=com')
|
13
|
+
end
|
14
|
+
end
|
data/spec/unit/user_spec.rb
CHANGED
@@ -66,9 +66,10 @@ describe 'Users' do
|
|
66
66
|
assert(User.all.blank?, "There shouldn't be any users in the database")
|
67
67
|
end
|
68
68
|
|
69
|
-
it "should
|
70
|
-
@user = User.
|
69
|
+
it "should not create user in the database" do
|
70
|
+
@user = User.find_for_ldap_authentication(:email => "example.user@test.com", :password => "secret")
|
71
71
|
assert(User.all.blank?)
|
72
|
+
assert(@user.new_record?)
|
72
73
|
end
|
73
74
|
|
74
75
|
describe "creating users is enabled" do
|
@@ -77,18 +78,19 @@ describe 'Users' do
|
|
77
78
|
end
|
78
79
|
|
79
80
|
it "should create a user in the database" do
|
80
|
-
@user = User.
|
81
|
+
@user = User.find_for_ldap_authentication(:email => "example.user@test.com", :password => "secret")
|
81
82
|
assert_equal(User.all.size, 1)
|
82
83
|
User.all.collect(&:email).should include("example.user@test.com")
|
84
|
+
assert(@user.persisted?)
|
83
85
|
end
|
84
86
|
|
85
87
|
it "should not create a user in the database if the password is wrong_secret" do
|
86
|
-
@user = User.
|
88
|
+
@user = User.find_for_ldap_authentication(:email => "example.user", :password => "wrong_secret")
|
87
89
|
assert(User.all.blank?, "There's users in the database")
|
88
90
|
end
|
89
91
|
|
90
|
-
it "should create a user if the user is not in LDAP" do
|
91
|
-
@user = User.
|
92
|
+
it "should not create a user if the user is not in LDAP" do
|
93
|
+
@user = User.find_for_ldap_authentication(:email => "wrong_secret.user@test.com", :password => "wrong_secret")
|
92
94
|
assert(User.all.blank?, "There's users in the database")
|
93
95
|
end
|
94
96
|
|
@@ -97,7 +99,7 @@ describe 'Users' do
|
|
97
99
|
@user = Factory.create(:user)
|
98
100
|
|
99
101
|
expect do
|
100
|
-
User.
|
102
|
+
User.find_for_ldap_authentication(:email => "EXAMPLE.user@test.com", :password => "secret")
|
101
103
|
end.to change { User.count }.by(1)
|
102
104
|
end
|
103
105
|
|
@@ -106,14 +108,14 @@ describe 'Users' do
|
|
106
108
|
@user = Factory.create(:user)
|
107
109
|
|
108
110
|
expect do
|
109
|
-
User.
|
111
|
+
User.find_for_ldap_authentication(:email => "EXAMPLE.user@test.com", :password => "secret")
|
110
112
|
end.to_not change { User.count }
|
111
113
|
end
|
112
114
|
|
113
115
|
it "should create a user with downcased email in the database if case insensitivity matters" do
|
114
116
|
::Devise.case_insensitive_keys = [:email]
|
115
117
|
|
116
|
-
@user = User.
|
118
|
+
@user = User.find_for_ldap_authentication(:email => "EXAMPLE.user@test.com", :password => "secret")
|
117
119
|
User.all.collect(&:email).should include("example.user@test.com")
|
118
120
|
end
|
119
121
|
end
|
@@ -167,7 +169,37 @@ describe 'Users' do
|
|
167
169
|
assert_equal false, @user.in_ldap_group?('cn=thisgroupdoesnotexist,ou=groups,dc=test,dc=com')
|
168
170
|
end
|
169
171
|
end
|
170
|
-
|
172
|
+
|
173
|
+
describe "check group membership w/out admin bind" do
|
174
|
+
before do
|
175
|
+
@user = Factory.create(:user)
|
176
|
+
::Devise.ldap_check_group_membership_without_admin = true
|
177
|
+
end
|
178
|
+
|
179
|
+
after do
|
180
|
+
::Devise.ldap_check_group_membership_without_admin = false
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should return true for user being in the users group" do
|
184
|
+
assert_equal true, @user.in_ldap_group?('cn=users,ou=groups,dc=test,dc=com')
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should return false for user being in the admins group" do
|
188
|
+
assert_equal false, @user.in_ldap_group?('cn=admins,ou=groups,dc=test,dc=com')
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should return false for a user being in a nonexistent group" do
|
192
|
+
assert_equal false, @user.in_ldap_group?('cn=thisgroupdoesnotexist,ou=groups,dc=test,dc=com')
|
193
|
+
end
|
194
|
+
|
195
|
+
# TODO: add a test that confirms the user's own binding is used rather
|
196
|
+
# than the admin binding by creating an LDAP user who can't do group
|
197
|
+
# lookups perhaps?
|
198
|
+
|
199
|
+
# TODO: add a test to demonstrate this function won't work on a user
|
200
|
+
# after the initial login request if the password isn't available. This
|
201
|
+
# might have to be more of a full stack test.
|
202
|
+
end
|
171
203
|
|
172
204
|
describe "use role attribute for authorization" do
|
173
205
|
before do
|
@@ -225,7 +257,7 @@ describe 'Users' do
|
|
225
257
|
end
|
226
258
|
|
227
259
|
it "should create a user in the database" do
|
228
|
-
@user = User.
|
260
|
+
@user = User.find_for_ldap_authentication(:uid => "example_user", :password => "secret")
|
229
261
|
assert_equal(User.all.size, 1)
|
230
262
|
User.all.collect(&:uid).should include("example_user")
|
231
263
|
end
|
@@ -236,7 +268,7 @@ describe 'Users' do
|
|
236
268
|
@foobar = 'foobar'
|
237
269
|
end
|
238
270
|
end
|
239
|
-
user = User.
|
271
|
+
user = User.find_for_ldap_authentication(:uid => "example_user", :password => "secret")
|
240
272
|
assert_equal 'foobar', user.instance_variable_get(:"@foobar")
|
241
273
|
User.class_eval do
|
242
274
|
undef ldap_before_save
|
@@ -244,9 +276,7 @@ describe 'Users' do
|
|
244
276
|
end
|
245
277
|
|
246
278
|
it "should not call ldap_before_save hook if not defined" do
|
247
|
-
|
248
|
-
should_be_validated Factory.create(:user, :uid => "example_user"), "secret"
|
249
|
-
end
|
279
|
+
should_be_validated Factory.create(:user, :uid => "example_user"), "secret"
|
250
280
|
end
|
251
281
|
end
|
252
282
|
end
|
@@ -279,9 +309,7 @@ describe 'Users' do
|
|
279
309
|
end
|
280
310
|
|
281
311
|
it "should not fail if config file has ssl: true" do
|
282
|
-
|
283
|
-
Devise::LDAP::Connection.new
|
284
|
-
end
|
312
|
+
Devise::LDAP::Connection.new
|
285
313
|
end
|
286
314
|
end
|
287
315
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_ldap_authenticatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Curtis Schiewek
|
@@ -10,180 +10,180 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2015-03-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: devise
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '3.0'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: net-ldap
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- -
|
33
|
+
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: 0.3.1
|
36
|
-
- - <
|
36
|
+
- - "<"
|
37
37
|
- !ruby/object:Gem::Version
|
38
38
|
version: 0.6.0
|
39
39
|
type: :runtime
|
40
40
|
prerelease: false
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ">="
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 0.3.1
|
46
|
-
- - <
|
46
|
+
- - "<"
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: 0.6.0
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: rake
|
51
51
|
requirement: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0.9'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '0.9'
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
64
|
name: rdoc
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '3'
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- -
|
74
|
+
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '3'
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
78
|
name: rails
|
79
79
|
requirement: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '4.0'
|
84
84
|
type: :development
|
85
85
|
prerelease: false
|
86
86
|
version_requirements: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '4.0'
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: sqlite3
|
93
93
|
requirement: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- -
|
95
|
+
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
98
|
type: :development
|
99
99
|
prerelease: false
|
100
100
|
version_requirements: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- -
|
102
|
+
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: '0'
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
106
|
name: factory_girl_rails
|
107
107
|
requirement: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- - ~>
|
109
|
+
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '1.0'
|
112
112
|
type: :development
|
113
113
|
prerelease: false
|
114
114
|
version_requirements: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- - ~>
|
116
|
+
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '1.0'
|
119
119
|
- !ruby/object:Gem::Dependency
|
120
120
|
name: factory_girl
|
121
121
|
requirement: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
|
-
- - ~>
|
123
|
+
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '2.0'
|
126
126
|
type: :development
|
127
127
|
prerelease: false
|
128
128
|
version_requirements: !ruby/object:Gem::Requirement
|
129
129
|
requirements:
|
130
|
-
- - ~>
|
130
|
+
- - "~>"
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: '2.0'
|
133
133
|
- !ruby/object:Gem::Dependency
|
134
134
|
name: rspec-rails
|
135
135
|
requirement: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
|
-
- -
|
137
|
+
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
140
|
type: :development
|
141
141
|
prerelease: false
|
142
142
|
version_requirements: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
|
-
- -
|
144
|
+
- - ">="
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
- !ruby/object:Gem::Dependency
|
148
148
|
name: database_cleaner
|
149
149
|
requirement: !ruby/object:Gem::Requirement
|
150
150
|
requirements:
|
151
|
-
- -
|
151
|
+
- - ">="
|
152
152
|
- !ruby/object:Gem::Version
|
153
153
|
version: '0'
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
156
|
version_requirements: !ruby/object:Gem::Requirement
|
157
157
|
requirements:
|
158
|
-
- -
|
158
|
+
- - ">="
|
159
159
|
- !ruby/object:Gem::Version
|
160
160
|
version: '0'
|
161
161
|
- !ruby/object:Gem::Dependency
|
162
162
|
name: capybara
|
163
163
|
requirement: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
|
-
- -
|
165
|
+
- - ">="
|
166
166
|
- !ruby/object:Gem::Version
|
167
167
|
version: '0'
|
168
168
|
type: :development
|
169
169
|
prerelease: false
|
170
170
|
version_requirements: !ruby/object:Gem::Requirement
|
171
171
|
requirements:
|
172
|
-
- -
|
172
|
+
- - ">="
|
173
173
|
- !ruby/object:Gem::Version
|
174
174
|
version: '0'
|
175
175
|
- !ruby/object:Gem::Dependency
|
176
176
|
name: launchy
|
177
177
|
requirement: !ruby/object:Gem::Requirement
|
178
178
|
requirements:
|
179
|
-
- -
|
179
|
+
- - ">="
|
180
180
|
- !ruby/object:Gem::Version
|
181
181
|
version: '0'
|
182
182
|
type: :development
|
183
183
|
prerelease: false
|
184
184
|
version_requirements: !ruby/object:Gem::Requirement
|
185
185
|
requirements:
|
186
|
-
- -
|
186
|
+
- - ">="
|
187
187
|
- !ruby/object:Gem::Version
|
188
188
|
version: '0'
|
189
189
|
description: Devise extension to allow authentication via LDAP
|
@@ -192,7 +192,7 @@ executables: []
|
|
192
192
|
extensions: []
|
193
193
|
extra_rdoc_files: []
|
194
194
|
files:
|
195
|
-
- .gitignore
|
195
|
+
- ".gitignore"
|
196
196
|
- CHANGELOG.md
|
197
197
|
- Gemfile
|
198
198
|
- MIT-LICENSE
|
@@ -277,6 +277,7 @@ files:
|
|
277
277
|
- spec/rails_app/script/rails
|
278
278
|
- spec/spec_helper.rb
|
279
279
|
- spec/support/factories.rb
|
280
|
+
- spec/unit/connection_spec.rb
|
280
281
|
- spec/unit/user_spec.rb
|
281
282
|
homepage: https://github.com/cschiewek/devise_ldap_authenticatable
|
282
283
|
licenses:
|
@@ -288,18 +289,89 @@ require_paths:
|
|
288
289
|
- lib
|
289
290
|
required_ruby_version: !ruby/object:Gem::Requirement
|
290
291
|
requirements:
|
291
|
-
- -
|
292
|
+
- - ">="
|
292
293
|
- !ruby/object:Gem::Version
|
293
294
|
version: '0'
|
294
295
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
295
296
|
requirements:
|
296
|
-
- -
|
297
|
+
- - ">="
|
297
298
|
- !ruby/object:Gem::Version
|
298
299
|
version: '0'
|
299
300
|
requirements: []
|
300
301
|
rubyforge_project:
|
301
|
-
rubygems_version: 2.
|
302
|
+
rubygems_version: 2.2.2
|
302
303
|
signing_key:
|
303
304
|
specification_version: 4
|
304
305
|
summary: Devise extension to allow authentication via LDAP
|
305
|
-
test_files:
|
306
|
+
test_files:
|
307
|
+
- spec/ldap/.gitignore
|
308
|
+
- spec/ldap/base.ldif
|
309
|
+
- spec/ldap/clear.ldif
|
310
|
+
- spec/ldap/local.schema
|
311
|
+
- spec/ldap/openldap-data/.gitignore
|
312
|
+
- spec/ldap/openldap-data/run/.gitignore
|
313
|
+
- spec/ldap/openldap-data/run/.gitkeep
|
314
|
+
- spec/ldap/run-server
|
315
|
+
- spec/ldap/server.pem
|
316
|
+
- spec/ldap/slapd-test.conf.erb
|
317
|
+
- spec/rails_app/Rakefile
|
318
|
+
- spec/rails_app/app/controllers/application_controller.rb
|
319
|
+
- spec/rails_app/app/controllers/posts_controller.rb
|
320
|
+
- spec/rails_app/app/helpers/application_helper.rb
|
321
|
+
- spec/rails_app/app/helpers/posts_helper.rb
|
322
|
+
- spec/rails_app/app/models/post.rb
|
323
|
+
- spec/rails_app/app/models/user.rb
|
324
|
+
- spec/rails_app/app/views/layouts/application.html.erb
|
325
|
+
- spec/rails_app/app/views/posts/index.html.erb
|
326
|
+
- spec/rails_app/config.ru
|
327
|
+
- spec/rails_app/config/application.rb
|
328
|
+
- spec/rails_app/config/boot.rb
|
329
|
+
- spec/rails_app/config/cucumber.yml
|
330
|
+
- spec/rails_app/config/database.yml
|
331
|
+
- spec/rails_app/config/environment.rb
|
332
|
+
- spec/rails_app/config/environments/development.rb
|
333
|
+
- spec/rails_app/config/environments/production.rb
|
334
|
+
- spec/rails_app/config/environments/test.rb
|
335
|
+
- spec/rails_app/config/initializers/backtrace_silencers.rb
|
336
|
+
- spec/rails_app/config/initializers/devise.rb
|
337
|
+
- spec/rails_app/config/initializers/inflections.rb
|
338
|
+
- spec/rails_app/config/initializers/mime_types.rb
|
339
|
+
- spec/rails_app/config/initializers/secret_token.rb
|
340
|
+
- spec/rails_app/config/initializers/session_store.rb
|
341
|
+
- spec/rails_app/config/ldap.yml
|
342
|
+
- spec/rails_app/config/ldap_with_boolean_ssl.yml
|
343
|
+
- spec/rails_app/config/ldap_with_erb.yml
|
344
|
+
- spec/rails_app/config/ldap_with_uid.yml
|
345
|
+
- spec/rails_app/config/locales/devise.en.yml
|
346
|
+
- spec/rails_app/config/locales/en.yml
|
347
|
+
- spec/rails_app/config/routes.rb
|
348
|
+
- spec/rails_app/config/ssl_ldap.yml
|
349
|
+
- spec/rails_app/config/ssl_ldap_with_erb.yml
|
350
|
+
- spec/rails_app/config/ssl_ldap_with_uid.yml
|
351
|
+
- spec/rails_app/db/migrate/20100708120448_devise_create_users.rb
|
352
|
+
- spec/rails_app/db/schema.rb
|
353
|
+
- spec/rails_app/features/manage_logins.feature
|
354
|
+
- spec/rails_app/features/step_definitions/login_steps.rb
|
355
|
+
- spec/rails_app/features/step_definitions/web_steps.rb
|
356
|
+
- spec/rails_app/features/support/env.rb
|
357
|
+
- spec/rails_app/features/support/paths.rb
|
358
|
+
- spec/rails_app/lib/tasks/.gitkeep
|
359
|
+
- spec/rails_app/lib/tasks/cucumber.rake
|
360
|
+
- spec/rails_app/public/404.html
|
361
|
+
- spec/rails_app/public/422.html
|
362
|
+
- spec/rails_app/public/500.html
|
363
|
+
- spec/rails_app/public/images/rails.png
|
364
|
+
- spec/rails_app/public/javascripts/application.js
|
365
|
+
- spec/rails_app/public/javascripts/controls.js
|
366
|
+
- spec/rails_app/public/javascripts/dragdrop.js
|
367
|
+
- spec/rails_app/public/javascripts/effects.js
|
368
|
+
- spec/rails_app/public/javascripts/prototype.js
|
369
|
+
- spec/rails_app/public/javascripts/rails.js
|
370
|
+
- spec/rails_app/public/stylesheets/.gitkeep
|
371
|
+
- spec/rails_app/script/cucumber
|
372
|
+
- spec/rails_app/script/rails
|
373
|
+
- spec/spec_helper.rb
|
374
|
+
- spec/support/factories.rb
|
375
|
+
- spec/unit/connection_spec.rb
|
376
|
+
- spec/unit/user_spec.rb
|
377
|
+
has_rdoc:
|