adauth 0.0.1pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ .DS_STORE
2
+ pkg/*
3
+ tmp/*
4
+ *~
5
+ spec/test_data.yml
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ adauth (0.0.1pre)
5
+ ruby-net-ldap
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.2)
11
+ rspec (2.6.0)
12
+ rspec-core (~> 2.6.0)
13
+ rspec-expectations (~> 2.6.0)
14
+ rspec-mocks (~> 2.6.0)
15
+ rspec-core (2.6.1)
16
+ rspec-expectations (2.6.0)
17
+ diff-lcs (~> 1.1.2)
18
+ rspec-mocks (2.6.0)
19
+ ruby-net-ldap (0.0.4)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ adauth!
26
+ rspec
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,64 @@
1
+ = {Adauth}[http://adauth.arcath.net/]
2
+
3
+ Easy to use Active Directory Authentication for Rails.
4
+
5
+ == Install
6
+
7
+ Add the Adauth gem to your Gemfile:
8
+
9
+ gem 'adauth'
10
+
11
+ and run a bundle install
12
+
13
+ == Usage
14
+
15
+ Create an initializer in _config/initilaizers_ called adauth.rb and place this code in it:
16
+
17
+ Adauth.configure do |c|
18
+ c.domain = "example.com" #The domain name used on your network e.g. example.com or example.local
19
+ c.server = "127.0.0.1" #The IP of any DC on your network
20
+ c.base = "dc=example, dc=com" #the base for your users.
21
+ end
22
+
23
+ c.port can also be used but defaults to 389 which is the default for AD/LDAP. For a full list of options see {Configuration}[...] on the wiki.
24
+
25
+ Thats enough to very basically run Adauth, and if you prefer complete control over how your authentication is handled you can use this method:
26
+
27
+ Adauth.authenticate(username, password)
28
+
29
+ Which has 2 possible return values nil if the users details are wrong or an instance of Adauth::User if the details are correct.
30
+
31
+ Adauth provides generators and helper methods for getting your application up and running.
32
+
33
+ == Developing
34
+
35
+ Obviously to test the AD functionality Adauth requires a working domain and a user to try logging in with. If you try running the tests without first creating the test_data.yml file then they will fail with this error:
36
+
37
+ Failure/Error: @yaml = YAML::load(File.open('spec/test_data.yml'))
38
+
39
+ You need to create a yaml file that looks like this:
40
+
41
+ domain:
42
+ domain: example.com
43
+ server: 127.0.0.1
44
+ port: 389
45
+ base: "dc=example, dc=com"
46
+ pass_allowed_groups:
47
+ - group
48
+ fail_allowed_groups:
49
+ - no_group
50
+
51
+ user:
52
+ login: username
53
+ password: password
54
+ group: group
55
+
56
+ The domain portion of this file is pretty self explanatory, they are the same as the code above for creating a domain connection. ALL options need to be set here.
57
+
58
+ The pass and fail allowed groups need to be an array with pass containing a group that the test user is a member of and fail containing a group that the test user isn't a member of. (The fail group doesn't have to exist)
59
+
60
+ The user is a user capable of logging into the domain, you can use your account here or any account on the domain. The group attribute needs to be set to a group that you are a member of so that the tests can make sure that the correct groups are picked up from AD.
61
+
62
+ Don't worry about this file making it into a pull request, it is in the .gitignore file so unless you remove it from there it wont be comitted.
63
+
64
+ If you make any additions/changes please add some tests for them.
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'adauth/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "adauth"
7
+ s.version = Adauth::Version
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Adam \"Arcath\" Laycock"]
10
+ s.email = ["gems@arcath.net"]
11
+ s.homepage = "http://adauth.arcath.net"
12
+ s.summary = "Provides Active Directory authentication for Rails"
13
+
14
+ s.add_development_dependency "rspec"
15
+ s.add_dependency "ruby-net-ldap"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'net/ldap'
2
+ require 'adauth/version'
3
+ require 'adauth/user'
4
+ require 'adauth/config'
5
+ require 'adauth/helpers'
6
+ require 'adauth/user_model' if defined? ActiveRecord
7
+
8
+ module Adauth
9
+ def self.authenticate(login, pass)
10
+ if @config.allowed_groups != []
11
+ user = Adauth::User.authenticate(login, pass)
12
+ (user && @config.allowed_groups != (@config.allowed_groups - user.groups)) ? user : nil
13
+ else
14
+ Adauth::User.authenticate(login, pass)
15
+ end
16
+ end
17
+
18
+ def self.configure
19
+ @config = Config.new
20
+ yield(@config)
21
+ end
22
+
23
+ def self.config
24
+ @config
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ module Adauth
2
+ class Config
3
+ attr_accessor :domain, :port, :base, :server, :allowed_groups
4
+
5
+ def initialize
6
+ @port = 389
7
+ @allowed_groups = []
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ module Adauth
2
+ module Helpers
3
+ def adauth_form
4
+ form_tag '/adauth', :id => "adauth_login" do
5
+ yield.html_safe
6
+ end
7
+ end
8
+
9
+ def default_adauth_form
10
+ adauth_form do
11
+ "<p>#{label_tag :username}:
12
+ #{text_field_tag :username}</p>
13
+ <p>#{label_tag :password}:
14
+ #{password_field_tag :password}</p>
15
+ <p>#{submit_tag "Login!"}</p>"
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ ActionView::Base.send :include, Adauth::Helpers if defined? ActionView
@@ -0,0 +1,85 @@
1
+ module Adauth
2
+ class User
3
+ ATTR_SV = {
4
+ :login => :samaccountname,
5
+ :first_name => :givenname,
6
+ :last_name => :sn,
7
+ :email => :mail,
8
+ :name => :name
9
+ }
10
+
11
+ ATTR_MV = {
12
+ :groups => [ :memberof,
13
+ Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ]
14
+ }
15
+
16
+ def self.authenticate(login, pass)
17
+ return nil if login.empty? or pass.empty?
18
+ conn = Net::LDAP.new :host => Adauth.config.server,
19
+ :port => Adauth.config.port,
20
+ :base => Adauth.config.base,
21
+ :auth => { :username => "#{login}@#{Adauth.config.domain}",
22
+ :password => pass,
23
+ :method => :simple }
24
+ if conn.bind and user = conn.search(:filter => "sAMAccountName=#{login}").first
25
+ return self.new(user)
26
+ else
27
+ return nil
28
+ end
29
+ rescue Net::LDAP::LdapError => e
30
+ return nil
31
+ end
32
+
33
+ def full_name
34
+ self.first_name + ' ' + self.last_name
35
+ end
36
+
37
+ def member_of?(group)
38
+ self.groups.include?(group)
39
+ end
40
+
41
+ private
42
+
43
+ def initialize(entry)
44
+ @entry = entry
45
+ self.class.class_eval do
46
+ generate_single_value_readers
47
+ generate_multi_value_readers
48
+ end
49
+ end
50
+
51
+ def self.generate_single_value_readers
52
+ ATTR_SV.each_pair do |k, v|
53
+ val, block = Array(v)
54
+ define_method(k) do
55
+ if @entry.attribute_names.include?(val)
56
+ if block.is_a?(Proc)
57
+ return block[@entry.send(val).to_s]
58
+ else
59
+ return @entry.send(val).to_s
60
+ end
61
+ else
62
+ return ''
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def self.generate_multi_value_readers
69
+ ATTR_MV.each_pair do |k, v|
70
+ val, block = Array(v)
71
+ define_method(k) do
72
+ if @entry.attribute_names.include?(val)
73
+ if block.is_a?(Proc)
74
+ return @entry.send(val).collect(&block)
75
+ else
76
+ return @entry.send(val)
77
+ end
78
+ else
79
+ return []
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,25 @@
1
+ module Adauth
2
+ module UserModel
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ def groups
8
+ group_strings.split(", ")
9
+ end
10
+
11
+ module ClassMethods
12
+ def return_and_create_with_adauth(adauth_user)
13
+ find_by_login(adauth_user.login) || create_user_with_adauth(adauth_user)
14
+ end
15
+
16
+ def create_user_with_adauth(adauth_user)
17
+ create! do |user|
18
+ user.login = adauth_user.login
19
+ user.group_strings = adauth_user.groups.join(", ")
20
+ user.name = adauth_user.name
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Adauth
2
+ Version = "0.0.1pre"
3
+ end
@@ -0,0 +1,14 @@
1
+ Description:
2
+ Default for MODEL_NAME is user
3
+ Default for MIGRATION_NAME is "create_(plural of MODEL_NAME)"
4
+ Creates a model for storing Adauth users which inherits from Adauth::UserModel
5
+
6
+ Example:
7
+ adauth:user_model
8
+ Will result in app/model/user.rb and a migration called create_users
9
+
10
+ adauth:user_model employee
11
+ Will result in app/model/employee.rb and a migration called create_employees
12
+
13
+ adauth:user_model employee add_adauth_to_employees
14
+ Will result in app/model/employee.rb and a migration called add_adauth_to_employees
@@ -0,0 +1,14 @@
1
+ class <%= migration_name_for_array.camelize %>
2
+ def self.up
3
+ create_table :<%= model_name.pluralize %> do |t|
4
+ t.string :login
5
+ t.string :group_strings
6
+ t.string :name
7
+ t.timestamps
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :<%= model_name.pluralize %>
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ class <%= model_name.camelize %> < ActiveRecord::Base
2
+ include Adauth::UserModel
3
+ end
@@ -0,0 +1,24 @@
1
+ module Adauth
2
+ module Generators
3
+ class UserModelGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ argument :model_name, :type => :string, :default => "user"
6
+ argument :migration_name, :type => :string, :default => false
7
+
8
+ def generate_user_model
9
+ template "model.rb.erb", "app/models/#{file_name}.rb"
10
+ template "migration.rb.erb", "db/migrate/#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_#{migration_name_for_array}.rb"
11
+ end
12
+
13
+ private
14
+
15
+ def file_name
16
+ model_name.underscore
17
+ end
18
+
19
+ def migration_name_for_array
20
+ migration_name || "create_#{model_name.pluralize}"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,92 @@
1
+ require 'lib/adauth'
2
+ require 'yaml'
3
+
4
+ describe Adauth, "#configure" do
5
+ it "should accept a block" do
6
+ Adauth.configure do |c|
7
+ c.domain = "example.com"
8
+ end
9
+ end
10
+ end
11
+
12
+ describe Adauth, "#config" do
13
+ before :each do
14
+ Adauth.configure do |c|
15
+ c.domain = "example.com"
16
+ c.base = "dc=example, dc=com"
17
+ c.server = "127.0.0.1"
18
+ end
19
+ end
20
+
21
+ it "should allow retrival of data" do
22
+ Adauth.config.domain.should == "example.com"
23
+ end
24
+
25
+ it "should set port to 389 if not set" do
26
+ Adauth.config.port.should == 389
27
+ end
28
+ end
29
+
30
+ describe Adauth, "#authenticate" do
31
+ before :each do
32
+ @yaml = YAML::load(File.open('spec/test_data.yml'))
33
+ Adauth.configure do |c|
34
+ c.domain = @yaml["domain"]["domain"]
35
+ c.server = @yaml["domain"]["server"]
36
+ c.port = @yaml["domain"]["port"]
37
+ c.base = @yaml["domain"]["base"]
38
+ end
39
+ end
40
+
41
+ it "should succesfully authenticate with the example user" do
42
+ Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"]).should be_a Adauth::User
43
+ end
44
+
45
+ it "should return nil for a failed bind" do
46
+ Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["group"]).should == nil
47
+ end
48
+
49
+ it "should return nil for a failed bind whilst using allowed groups" do
50
+ Adauth.config.allowed_groups = @yaml["domain"]["pass_allowed_groups"]
51
+ Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["group"]).should be_nil
52
+ end
53
+
54
+ it "should allow users who are in an allowed group" do
55
+ Adauth.config.allowed_groups = @yaml["domain"]["pass_allowed_groups"]
56
+ Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"]).should be_a Adauth::User
57
+ end
58
+
59
+ it "should dis-allow users who are not in an allowed group" do
60
+ Adauth.config.allowed_groups = @yaml["domain"]["fail_allowed_groups"]
61
+ Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"]).should be_nil
62
+ end
63
+ end
64
+
65
+ describe Adauth::User do
66
+ before :each do
67
+ @yaml = YAML::load(File.open('spec/test_data.yml'))
68
+ Adauth.configure do |c|
69
+ c.domain = @yaml["domain"]["domain"]
70
+ c.server = @yaml["domain"]["server"]
71
+ c.port = @yaml["domain"]["port"]
72
+ c.base = @yaml["domain"]["base"]
73
+ end
74
+ @user = Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"])
75
+ end
76
+
77
+ it "should return groups for an authenticated user" do
78
+ @user.groups.should be_a Array
79
+ end
80
+
81
+ it "should return true for a member_of test using the users group" do
82
+ @user.member_of?(@yaml["user"]["group"]).should == true
83
+ end
84
+
85
+ it "should return false for a member_of test using the users password" do
86
+ @user.member_of?(@yaml["user"]["password"]).should == false
87
+ end
88
+
89
+ it "should have the correct user" do
90
+ @user.login.should == @yaml["user"]["login"]
91
+ end
92
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: adauth
3
+ version: !ruby/object:Gem::Version
4
+ hash: 961915968
5
+ prerelease: 5
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ - pre
11
+ version: 0.0.1pre
12
+ platform: ruby
13
+ authors:
14
+ - Adam "Arcath" Laycock
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-06-06 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rspec
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: ruby-net-ldap
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description:
51
+ email:
52
+ - gems@arcath.net
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files: []
58
+
59
+ files:
60
+ - .gitignore
61
+ - Gemfile
62
+ - Gemfile.lock
63
+ - Rakefile
64
+ - Readme.rdoc
65
+ - adauth.gemspec
66
+ - lib/adauth.rb
67
+ - lib/adauth/config.rb
68
+ - lib/adauth/helpers.rb
69
+ - lib/adauth/user.rb
70
+ - lib/adauth/user_model.rb
71
+ - lib/adauth/version.rb
72
+ - lib/generators/adauth/user_model/USAGE
73
+ - lib/generators/adauth/user_model/templates/migration.rb.erb
74
+ - lib/generators/adauth/user_model/templates/model.rb.erb
75
+ - lib/generators/adauth/user_model/user_model_generator.rb
76
+ - spec/adauth_spec.rb
77
+ has_rdoc: true
78
+ homepage: http://adauth.arcath.net
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options: []
83
+
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">"
99
+ - !ruby/object:Gem::Version
100
+ hash: 25
101
+ segments:
102
+ - 1
103
+ - 3
104
+ - 1
105
+ version: 1.3.1
106
+ requirements: []
107
+
108
+ rubyforge_project:
109
+ rubygems_version: 1.6.2
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Provides Active Directory authentication for Rails
113
+ test_files:
114
+ - spec/adauth_spec.rb