dm-devise 0.1.0

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.
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
+