dm-devise 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/dm-devise.gemspec ADDED
@@ -0,0 +1,105 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{dm-devise}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jared Morgan"]
12
+ s.date = %q{2010-07-06}
13
+ s.description = %q{dm-devise adds DataMapper support to devise (http://github.com/plataformatec/devise) for authentication support for Rails}
14
+ s.email = %q{jmorgan@morgancreative.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "dm-devise.gemspec",
28
+ "lib/devise/orm/data_mapper.rb",
29
+ "lib/devise/orm/data_mapper/compatibility.rb",
30
+ "lib/devise/orm/data_mapper/date_time.rb",
31
+ "lib/devise/orm/data_mapper/dm-validations.rb",
32
+ "lib/devise/orm/data_mapper/schema.rb",
33
+ "lib/devise/orm/data_mapper_active_model.rb",
34
+ "lib/dm-devise/version.rb",
35
+ "lib/generators/data_mapper/devise_generator.rb",
36
+ "test/orm/data_mapper.rb",
37
+ "test/orm/data_mapper_active_model.rb",
38
+ "test/overrides/data_mapper_test.rb",
39
+ "test/overrides/dm_validations_test.rb",
40
+ "test/rails_app/app/data_mapper/admin.rb",
41
+ "test/rails_app/app/data_mapper/shim.rb",
42
+ "test/rails_app/app/data_mapper/user.rb",
43
+ "test/rails_app/app/data_mapper_active_model/admin.rb",
44
+ "test/rails_app/app/data_mapper_active_model/shim.rb",
45
+ "test/rails_app/app/data_mapper_active_model/user.rb",
46
+ "test/rails_app/config/application.rb",
47
+ "test/rails_app/config/environment.rb",
48
+ "test/test_helper.rb"
49
+ ]
50
+ s.homepage = %q{http://github.com/jm81/dm-devise}
51
+ s.rdoc_options = ["--charset=UTF-8"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = %q{1.3.7}
54
+ s.summary = %q{Support for using DataMapper ORM with devise}
55
+ s.test_files = [
56
+ "test/test_helper.rb",
57
+ "test/rails_app/config/environment.rb",
58
+ "test/rails_app/config/application.rb",
59
+ "test/rails_app/app/data_mapper/admin.rb",
60
+ "test/rails_app/app/data_mapper/shim.rb",
61
+ "test/rails_app/app/data_mapper/user.rb",
62
+ "test/rails_app/app/data_mapper_active_model/admin.rb",
63
+ "test/rails_app/app/data_mapper_active_model/shim.rb",
64
+ "test/rails_app/app/data_mapper_active_model/user.rb",
65
+ "test/overrides/data_mapper_test.rb",
66
+ "test/overrides/dm_validations_test.rb",
67
+ "test/orm/data_mapper.rb",
68
+ "test/orm/data_mapper_active_model.rb"
69
+ ]
70
+
71
+ if s.respond_to? :specification_version then
72
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
73
+ s.specification_version = 3
74
+
75
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
76
+ s.add_runtime_dependency(%q<dm-core>, ["~> 1.0.0"])
77
+ s.add_runtime_dependency(%q<dm-migrations>, ["~> 1.0.0"])
78
+ s.add_runtime_dependency(%q<dm-validations>, ["~> 1.0.0"])
79
+ s.add_runtime_dependency(%q<dm-serializer>, ["~> 1.0.0"])
80
+ s.add_runtime_dependency(%q<dm-timestamps>, ["~> 1.0.0"])
81
+ s.add_runtime_dependency(%q<dm-rails>, ["~> 1.0.0"])
82
+ s.add_runtime_dependency(%q<warden>, ["~> 0.10.7"])
83
+ s.add_runtime_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
84
+ else
85
+ s.add_dependency(%q<dm-core>, ["~> 1.0.0"])
86
+ s.add_dependency(%q<dm-migrations>, ["~> 1.0.0"])
87
+ s.add_dependency(%q<dm-validations>, ["~> 1.0.0"])
88
+ s.add_dependency(%q<dm-serializer>, ["~> 1.0.0"])
89
+ s.add_dependency(%q<dm-timestamps>, ["~> 1.0.0"])
90
+ s.add_dependency(%q<dm-rails>, ["~> 1.0.0"])
91
+ s.add_dependency(%q<warden>, ["~> 0.10.7"])
92
+ s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
93
+ end
94
+ else
95
+ s.add_dependency(%q<dm-core>, ["~> 1.0.0"])
96
+ s.add_dependency(%q<dm-migrations>, ["~> 1.0.0"])
97
+ s.add_dependency(%q<dm-validations>, ["~> 1.0.0"])
98
+ s.add_dependency(%q<dm-serializer>, ["~> 1.0.0"])
99
+ s.add_dependency(%q<dm-timestamps>, ["~> 1.0.0"])
100
+ s.add_dependency(%q<dm-rails>, ["~> 1.0.0"])
101
+ s.add_dependency(%q<warden>, ["~> 0.10.7"])
102
+ s.add_dependency(%q<bcrypt-ruby>, ["~> 2.1.2"])
103
+ end
104
+ end
105
+
@@ -0,0 +1,23 @@
1
+ require 'devise/orm/data_mapper/compatibility'
2
+ require 'devise/orm/data_mapper/schema'
3
+ require 'devise/orm/data_mapper/date_time'
4
+ require 'devise/orm/data_mapper/dm-validations'
5
+
6
+ module Devise
7
+ module Orm
8
+ module DataMapper
9
+ module Hook
10
+ def devise_modules_hook!
11
+ extend Schema
12
+ include Compatibility
13
+ yield
14
+ return unless Devise.apply_schema
15
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ DataMapper::Model.append_extensions(Devise::Models)
23
+ DataMapper::Model.append_extensions(Devise::Orm::DataMapper::Hook)
@@ -0,0 +1,69 @@
1
+ module Devise
2
+ module Orm
3
+ module DataMapper
4
+ module Compatibility
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ # Hooks for confirmable
9
+ def before_create(*args)
10
+ wrap_hook(:before, :create, *args)
11
+ end
12
+
13
+ def after_create(*args)
14
+ wrap_hook(:after, :create, *args)
15
+ end
16
+
17
+ def before_save(*args)
18
+ wrap_hook(:before, :save, *args)
19
+ end
20
+
21
+ def wrap_hook(action, method, *args)
22
+ options = args.extract_options!
23
+
24
+ args.each do |callback|
25
+ callback_method = :"#{callback}_callback_wrap"
26
+ send action, method, callback_method
27
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
28
+ def #{callback_method}
29
+ #{callback} if #{options[:if] || true}
30
+ end
31
+ METHOD
32
+ end
33
+ end
34
+
35
+ # Add ActiveRecord like finder
36
+ def find(*args)
37
+ case args.first
38
+ when :first, :all
39
+ send(args.shift, *args)
40
+ else
41
+ get(*args)
42
+ end
43
+ end
44
+ end
45
+
46
+ def changed?
47
+ dirty?
48
+ end
49
+
50
+ def save(options=nil)
51
+ if options.is_a?(Hash) && options[:validate] == false
52
+ save!
53
+ else
54
+ # valid? checking isn't added automatically with ActiveModel
55
+ valid? && super()
56
+ end
57
+ end
58
+
59
+ def update_attributes(*args)
60
+ update(*args)
61
+ end
62
+
63
+ def invalid?
64
+ !valid?
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,6 @@
1
+ # Add DateTime#gmtime method if needed.
2
+ class DateTime
3
+ unless method_defined?(:gmtime)
4
+ delegate :gmtime, :to => :to_time
5
+ end
6
+ end
@@ -0,0 +1,55 @@
1
+ module DataMapper
2
+ module Validate
3
+
4
+ # Monkey-patch ValidationErrors to support generation of error message from
5
+ # a Symbol. This does not translate, consistent with normal DataMapper
6
+ # operation. Set DataMapper::Validate::ValidationErrors.default_error_messages
7
+ # if alternate messages are needed (after devise has been initialized).
8
+ class ValidationErrors
9
+ alias_method :original_add, :add
10
+
11
+ # If the message is a Symbol, allow +default_error_message+ to generate
12
+ # the message, including translation.
13
+ def add(field_name, message)
14
+ if message.kind_of?(Symbol)
15
+ message = self.class.default_error_message(message, field_name)
16
+ end
17
+ original_add(field_name, message) unless errors[field_name].include?(message)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # Default error messages consistent with ActiveModel messages and devise
24
+ # expectations.
25
+ DataMapper::Validate::ValidationErrors.default_error_messages = {
26
+ :absent => '%s must be absent',
27
+ :inclusion => '%s is not included in the list',
28
+ :exclusion => '%s is reserved',
29
+ :invalid => '%s is invalid',
30
+ :confirmation => "%s doesn't match confirmation",
31
+ :accepted => '%s must be accepted',
32
+ :nil => '%s must not be nil',
33
+ :empty => "%s can't be empty",
34
+ :blank => "%s can't be blank",
35
+ :length_between => '%s must be between %s and %s characters long',
36
+ :too_long => '%s is too long (maximum is %s characters)',
37
+ :too_short => '%s is too short (minimum is %s characters)',
38
+ :wrong_length => '%s "is the wrong length (should be %s characters)"',
39
+ :taken => '%s has already been taken',
40
+ :not_a_number => '%s is not a number',
41
+ :not_an_integer => '%s must be an integer',
42
+ :greater_than => '%s must be greater than %s',
43
+ :greater_than_or_equal_to => '%s must be greater than or equal to %s',
44
+ :equal_to => '%s must be equal to %s',
45
+ :not_equal_to => '%s must not be equal to %s',
46
+ :less_than => '%s must be less than %s',
47
+ :less_than_or_equal_to => '%s must be less than or equal to %s',
48
+ :value_between => '%s must be between %s and %s',
49
+ :odd => 'must be odd',
50
+ :even => 'must be even',
51
+ :primitive => '%s must be of type %s',
52
+ :not_found => '%s not found',
53
+ :already_confirmed => '%s was already confirmed',
54
+ :not_locked => '%s was not locked'
55
+ }
@@ -0,0 +1,31 @@
1
+ module Devise
2
+ module Orm
3
+ module DataMapper
4
+ module Schema
5
+ include Devise::Schema
6
+
7
+ SCHEMA_OPTIONS = {
8
+ :null => :required,
9
+ :limit => :length
10
+ }
11
+
12
+ # Tell how to apply schema methods. This automatically maps :limit to
13
+ # :length and :null to :required.
14
+ def apply_devise_schema(name, type, options={})
15
+ SCHEMA_OPTIONS.each do |old_key, new_key|
16
+ next unless options.key?(old_key)
17
+ if :null == old_key
18
+ # :required is opposite of :null
19
+ options[new_key] = !options.delete(old_key)
20
+ else
21
+ options[new_key] = options.delete(old_key)
22
+ end
23
+ end
24
+
25
+ options.delete(:default) if options[:default].nil?
26
+ property name, type, options
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ require 'devise/orm/data_mapper/compatibility'
2
+ require 'devise/orm/data_mapper/schema'
3
+ require 'devise/orm/data_mapper/date_time'
4
+
5
+ module Devise
6
+ module Orm
7
+ module DataMapper
8
+ module Hook
9
+ def devise_modules_hook!
10
+ extend Schema
11
+ include Compatibility
12
+ include ActiveModel::Validations
13
+ class << self; attr_reader :descendants; end;
14
+
15
+ def self.validates_uniqueness_of(*fields)
16
+ validates_with UniquenessValidator, _merge_attributes(fields)
17
+ end
18
+
19
+ yield
20
+ return unless Devise.apply_schema
21
+ devise_modules.each { |m| send(m) if respond_to?(m, true) }
22
+ end
23
+ end
24
+
25
+ class UniquenessValidator < ActiveModel::EachValidator
26
+ def validate_each(target, attribute, value)
27
+ resource = ::DataMapper.repository(target.repository.name) { target.model.first(attribute => value) }
28
+ if resource.nil? || (target.saved? && resource.key == target.key)
29
+ return true
30
+ else
31
+ target.errors.add(attribute, :taken)
32
+ return false
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ DataMapper::Model.append_extensions(Devise::Models)
41
+ DataMapper::Model.append_extensions(Devise::Orm::DataMapper::Hook)
@@ -0,0 +1,5 @@
1
+ module DataMapper
2
+ module Devise
3
+ VERSION = "0.1.0".freeze
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ require 'generators/devise/orm_helpers'
2
+
3
+ module DataMapper
4
+ module Generators
5
+ class DeviseGenerator < Rails::Generators::NamedBase
6
+ include Devise::Generators::OrmHelpers
7
+
8
+ def generate_model
9
+ invoke "data_mapper:model", [name] unless model_exists?
10
+ end
11
+
12
+ def inject_devise_content
13
+ inject_into_file model_path, model_contents, :after => "include DataMapper::Resource\n"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ require 'rails/test_help'
2
+
3
+ DataMapper.auto_migrate!
4
+
5
+ class ActiveSupport::TestCase
6
+ setup do
7
+ User.all.destroy!
8
+ Admin.all.destroy!
9
+ end
10
+ end
11
+
12
+ module DataMapper
13
+ module Validate
14
+ class ValidationErrors
15
+
16
+ # ActiveModel prepends field names in +#full_messages+, and so the
17
+ # expected result of calling errors[field_name] will not include the
18
+ # field name in the message. However, DM expects the field name to be
19
+ # included in the original message. Assuming that the field name will
20
+ # begin the message, just strip it out (plus the following space) for
21
+ # testing purposes. This has no effect on #full_messages.
22
+ def [](property_name)
23
+ if property_errors = errors[property_name.to_sym]
24
+ property_errors.collect do |message|
25
+ message[(property_name.to_s.length + 1)..-1]
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails/test_help'
2
+
3
+ DataMapper.auto_migrate!
4
+
5
+ class ActiveSupport::TestCase
6
+ setup do
7
+ User.all.destroy!
8
+ Admin.all.destroy!
9
+ end
10
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+
3
+ # This file contains test cases that override devise tests, in the cases that
4
+ # the difference is values from DM versus those expected by devise is not
5
+ # particularly important and getting DM to pass the original devise tests would
6
+ # be difficult.
7
+ #
8
+ # This file contains tests shared by both data_mapper and
9
+ # data_mapper_active_model ORM setups.
10
+ # Tests specific to the data_mapper orm which uses dm-validations are in dm_validations_test.rb
11
+ # Tests specific to the data_mapper_active_model orm which uses ActiveModel
12
+ # validations would be in active_model_test.rb, but there aren't any (I would
13
+ # be rather surprised if there ever were any).
14
+ #
15
+ # For each test, an explanation is given as to why I chose to override the test,
16
+ # and the original assertion is commented above the DM-specific assertion.
17
+
18
+ class TrackableHooksTest < ActionController::IntegrationTest
19
+
20
+ undef test_current_and_last_sign_in_timestamps_are_updated_on_each_sign_in
21
+
22
+ # DataMapper uses a DateTime type where ActiveRecord uses Time. The test is
23
+ # that the tested properties are being set, so just check for kind_of?(DateTime)
24
+ # instead of kind_of?(Time)
25
+ test "current and last sign in timestamps are updated on each sign in" do
26
+ user = create_user
27
+ assert_nil user.current_sign_in_at
28
+ assert_nil user.last_sign_in_at
29
+
30
+ sign_in_as_user
31
+ user.reload
32
+
33
+ # assert_kind_of Time, user.current_sign_in_at
34
+ # assert_kind_of Time, user.last_sign_in_at
35
+ assert_kind_of DateTime, user.current_sign_in_at
36
+ assert_kind_of DateTime, user.last_sign_in_at
37
+
38
+ assert_equal user.current_sign_in_at, user.last_sign_in_at
39
+ assert user.current_sign_in_at >= user.created_at
40
+
41
+ visit destroy_user_session_path
42
+ new_time = 2.seconds.from_now
43
+ Time.stubs(:now).returns(new_time)
44
+
45
+ sign_in_as_user
46
+ user.reload
47
+ assert user.current_sign_in_at > user.last_sign_in_at
48
+ end
49
+ end
50
+