Permalink
Browse files

first commit of imapable

  • Loading branch information...
0 parents commit 796bb68c9a412ea916ceb60693930fea7cb6f2e5 @joshk committed Mar 26, 2010
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2010 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13 README
@@ -0,0 +1,13 @@
+Devise-Imapable
+==============
+
+Don't have LDAP available at your organisation? Use imapable!.
+
+
+Example
+=======
+
+Coming soon.
+
+
+Copyright (c) 2010 Josh Kalderimis, released under the MIT license
23 Rakefile
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the devise_imapable plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the devise_imapable plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'DeviseImapable'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
24 lib/devise_imapable.rb
@@ -0,0 +1,24 @@
+# encoding: utf-8
+require 'devise'
+
+require 'devise_imapable/model'
+require 'devise_imapable/schema'
+require 'devise_imapable/imap_connection'
+
+module Devise
+ # imap server address for authentication.
+ mattr_accessor :imap_server
+ @@imap_server = nil
+end
+
+# Add +:imapable+ strategy to defaults.
+#
+Devise.add_module(:imapable,
+ :strategy => true,
+ :controller => :sessions,
+ :model => 'devise_imapable/model',
+ :routes => :imapable)
+
+
+# load the routes
+require 'devise_imapable/routes'
19 lib/devise_imapable/imap_connection.rb
@@ -0,0 +1,19 @@
+require 'net/imap'
+
+module Devise
+
+ module ImapAdapter
+
+ def self.valid_credentials?(username, password)
+ imap = Net::IMAP.new(::Devise.imap_server)
+ imap.authenticate("cram-md5", username, password)
+ true
+ rescue Net::IMAP::ResponseError => e
+ false
+ # ensure
+ # imap.disconnect
+ end
+
+ end
+
+end
70 lib/devise_imapable/model.rb
@@ -0,0 +1,70 @@
+require 'devise_imapable/strategy'
+
+module Devise
+ module Models
+ # Imapable Module, responsible for validating the user credentials via an imap server and
+ # checking authenticity of a user while signing in.
+ #
+ # Examples:
+ #
+ # User.authenticate('email@test.com', 'password123') # returns authenticated user or nil
+ # User.find(1).valid_password?('password123') # returns true/false
+ #
+ module Imapable
+ def self.included(base)
+ # should assert that authenticatable is not included
+ base.class_eval do
+ extend ClassMethods
+
+ attr_accessor :password
+ end
+ end
+
+ # Set password and password confirmation to nil
+ def clean_up_passwords
+ self.password = nil
+ end
+
+ # def update_with_password(params={})
+ # # have a look into this later
+ # end
+
+ # Verifies whether an +incoming_authentication_token+ (i.e. from single access URL)
+ # is the user authentication token.
+ def valid_imap_authentication?(password)
+ Devise::ImapAdapter.valid_credentials?(self.email, password)
+ end
+
+ module ClassMethods
+ # Authenticate a user based on configured attribute keys. Returns the
+ # authenticated user if it's valid or nil.
+ def authenticate_with_imap(attributes={})
+ return unless attributes[:email].present?
+ conditions = attributes.slice(:email)
+ resource = find_or_initialize_for_authentication(conditions)
+
+ if resource.try(:valid_imap_authentication?, attributes[:password])
+ resource.new_record? ? create(conditions) : resource
+ end
+ end
+
+
+ protected
+
+ # Find first record based on conditions given (ie by the sign in form).
+ # Overwrite to add customized conditions, create a join, or maybe use a
+ # namedscope to filter records while authenticating.
+ # Example:
+ #
+ # def self.find_for_authentication(conditions={})
+ # conditions[:active] = true
+ # find(:first, :conditions => conditions)
+ # end
+ #
+ def find_or_initialize_for_authentication(conditions)
+ find(:first, :conditions => conditions) || new(conditions)
+ end
+ end
+ end
+ end
+end
12 lib/devise_imapable/routes.rb
@@ -0,0 +1,12 @@
+ActionController::Routing::RouteSet::Mapper.class_eval do
+
+ protected
+
+ # reuse the session routes and controller
+ def imapable(routes, mapping)
+ unless mapping.to.included_modules.include?(Devise::Models::Authenticatable)
+ authenticatable(routes, mapping)
+ end
+ end
+
+end
13 lib/devise_imapable/schema.rb
@@ -0,0 +1,13 @@
+Devise::Schema.class_eval do
+
+ # Creates email
+ #
+ # == Options
+ # * :null - When true, allow columns to be null.
+ def imapable(options={})
+ null = options[:null] || false
+
+ apply_schema :email, String, :null => null
+ end
+
+end
36 lib/devise_imapable/strategy.rb
@@ -0,0 +1,36 @@
+require 'devise/strategies/base'
+
+module Devise
+ module Strategies
+ # Strategy for signing in a user based on his email and password using imap.
+ # Redirects to sign_in page if it's not authenticated
+ class Imapable < Base
+ def valid?
+ valid_controller? && valid_params? && mapping.to.respond_to?(:authenticate_with_imap)
+ end
+
+ # Authenticate a user based on email and password params, returning to warden
+ # success and the authenticated user if everything is okay. Otherwise redirect
+ # to sign in page.
+ def authenticate!
+ if resource = mapping.to.authenticate_with_imap(params[scope])
+ success!(resource)
+ else
+ fail!(:invalid)
+ end
+ end
+
+ protected
+
+ def valid_controller?
+ params[:controller] == 'sessions'
+ end
+
+ def valid_params?
+ params[scope] && params[scope][:password].present?
+ end
+ end
+ end
+end
+
+Warden::Strategies.add(:authenticatable, Devise::Strategies::Imapable)
2 rails/init.rb
@@ -0,0 +1,2 @@
+# Include hook code here
+require 'devise_imapable'
8 test/devise_imapable_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class DeviseImapableTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
3 test/test_helper.rb
@@ -0,0 +1,3 @@
+require 'rubygems'
+require 'active_support'
+require 'active_support/test_case'

0 comments on commit 796bb68

Please sign in to comment.