device-approvable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c21253cd759309683db52b43a6c777577d7684eb
4
+ data.tar.gz: 1e4ddfe6cac7e5906577bb37f44dd0c66032e02a
5
+ SHA512:
6
+ metadata.gz: c4d845dd21884888fdb33ae2cf9574fd3360408ac3f1717d95811b9f74cc7c0c6fc5aff3f62dbec9bfd55c100c574514e7cd925035754a1e608a89b6a952084a
7
+ data.tar.gz: 8e82c2f68825782194191631b8d87516c8652df4f4f98b11a469eac0ed49be286f37753ac4175bafabc9c49b035ce4ae14d1482629a4fc62e09f8cf74828f9fa
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "rdoc", "~> 3.12"
11
+ gem "bundler", "~> 1.0"
12
+ gem "jeweler", "~> 2.0.1"
13
+ gem "simplecov", ">= 0"
14
+ end
@@ -0,0 +1,80 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.2.1)
5
+ i18n (~> 0.7)
6
+ json (~> 1.7, >= 1.7.7)
7
+ minitest (~> 5.1)
8
+ thread_safe (~> 0.3, >= 0.3.4)
9
+ tzinfo (~> 1.1)
10
+ addressable (2.3.8)
11
+ builder (3.2.2)
12
+ descendants_tracker (0.0.4)
13
+ thread_safe (~> 0.3, >= 0.3.1)
14
+ docile (1.1.5)
15
+ faraday (0.9.1)
16
+ multipart-post (>= 1.2, < 3)
17
+ git (1.2.9.1)
18
+ github_api (0.12.3)
19
+ addressable (~> 2.3)
20
+ descendants_tracker (~> 0.0.4)
21
+ faraday (~> 0.8, < 0.10)
22
+ hashie (>= 3.3)
23
+ multi_json (>= 1.7.5, < 2.0)
24
+ nokogiri (~> 1.6.3)
25
+ oauth2
26
+ hashie (3.4.1)
27
+ highline (1.7.1)
28
+ i18n (0.7.0)
29
+ jeweler (2.0.1)
30
+ builder
31
+ bundler (>= 1.0)
32
+ git (>= 1.2.5)
33
+ github_api
34
+ highline (>= 1.6.15)
35
+ nokogiri (>= 1.5.10)
36
+ rake
37
+ rdoc
38
+ json (1.8.2)
39
+ jwt (1.4.1)
40
+ mini_portile (0.6.2)
41
+ minitest (5.5.1)
42
+ multi_json (1.11.0)
43
+ multi_xml (0.5.5)
44
+ multipart-post (2.0.0)
45
+ nokogiri (1.6.6.2)
46
+ mini_portile (~> 0.6.0)
47
+ oauth2 (1.0.0)
48
+ faraday (>= 0.8, < 0.10)
49
+ jwt (~> 1.0)
50
+ multi_json (~> 1.3)
51
+ multi_xml (~> 0.5)
52
+ rack (~> 1.2)
53
+ rack (1.6.0)
54
+ rake (10.4.2)
55
+ rdoc (3.12.2)
56
+ json (~> 1.4)
57
+ shoulda (3.5.0)
58
+ shoulda-context (~> 1.0, >= 1.0.1)
59
+ shoulda-matchers (>= 1.4.1, < 3.0)
60
+ shoulda-context (1.2.1)
61
+ shoulda-matchers (2.8.0)
62
+ activesupport (>= 3.0.0)
63
+ simplecov (0.9.2)
64
+ docile (~> 1.1.0)
65
+ multi_json (~> 1.0)
66
+ simplecov-html (~> 0.9.0)
67
+ simplecov-html (0.9.0)
68
+ thread_safe (0.3.5)
69
+ tzinfo (1.2.2)
70
+ thread_safe (~> 0.1)
71
+
72
+ PLATFORMS
73
+ ruby
74
+
75
+ DEPENDENCIES
76
+ bundler (~> 1.0)
77
+ jeweler (~> 2.0.1)
78
+ rdoc (~> 3.12)
79
+ shoulda
80
+ simplecov
data/README ADDED
@@ -0,0 +1,5 @@
1
+ An approvable module. This includes all confirmable functions as approval should happen before confirmation.
2
+
3
+ Workflow:
4
+
5
+ Admin email should be added to the configuration. When user signs up admin receives email with link to approve user. Admin clicks link with token. User is approved. Confirmation email gets sent to user. User clicks confirmation link. Profit.
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "device-approvable"
18
+ gem.homepage = "http://github.com/eggie5/device-approvable"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Oh so perfect}
21
+ gem.description = %Q{adds feature to devise}
22
+ gem.email = "eggie5@gmail.com"
23
+ gem.authors = ["Alex Egg"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ desc "Code coverage detail"
36
+ task :simplecov do
37
+ ENV['COVERAGE'] = "true"
38
+ Rake::Task['test'].execute
39
+ end
40
+
41
+ task :default => :test
42
+
43
+ require 'rdoc/task'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "device-approvable #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,110 @@
1
+ require 'devise/approvable_mailer'
2
+ # Use this hook to configure devise mailer, warden hooks and so forth. The first
3
+ # four configuration values can also be set straight in your models.
4
+ Devise.setup do |config|
5
+ # Configure the e-mail address which will be shown in DeviseMailer.
6
+ config.mailer_sender = "support@yoursite.ca" # .CA because clearly you're Canadian
7
+ config.approval_recepient = "admin@yourcandaiansite.ca"
8
+
9
+ # Configure the content type of DeviseMailer mails (defaults to text/html")
10
+ # config.mailer_content_type = "text/plain"
11
+
12
+ # ==> Configuration for :authenticatable
13
+ # Invoke `rake secret` and use the printed value to setup a pepper to generate
14
+ # the encrypted password. By default no pepper is used.
15
+ # config.pepper = "rake secret output"
16
+
17
+ # Configure how many times you want the password is reencrypted. Default is 10.
18
+ # config.stretches = 10
19
+
20
+ # Define which will be the encryption algorithm. Supported algorithms are :sha1
21
+ # (default), :sha512 and :bcrypt. Devise also supports encryptors from others
22
+ # authentication tools as :clearance_sha1, :authlogic_sha512 (then you should set
23
+ # stretches above to 20 for default behavior) and :restful_authentication_sha1
24
+ # (then you should set stretches to 10, and copy REST_AUTH_SITE_KEY to pepper)
25
+ # config.encryptor = :sha1
26
+
27
+ # Configure which keys are used when authenticating an user. By default is
28
+ # just :email. You can configure it to use [:username, :subdomain], so for
29
+ # authenticating an user, both parameters are required. Remember that those
30
+ # parameters are used only when authenticating and not when retrieving from
31
+ # session. If you need permissions, you should implement that in a before filter.
32
+ # config.authentication_keys = [ :email ]
33
+
34
+ # The realm used in Http Basic Authentication
35
+ # config.http_authentication_realm = "Application"
36
+
37
+ # ==> Configuration for :confirmable
38
+ # The time you want give to your user to confirm his account. During this time
39
+ # he will be able to access your application without confirming. Default is nil.
40
+ # config.confirm_within = 2.days
41
+
42
+ # ==> Configuration for :rememberable
43
+ # The time the user will be remembered without asking for credentials again.
44
+ # config.remember_for = 2.weeks
45
+
46
+ # ==> Configuration for :timeoutable
47
+ # The time you want to timeout the user session without activity. After this
48
+ # time the user will be asked for credentials again.
49
+ # config.timeout_in = 10.minutes
50
+
51
+ # ==> Configuration for :lockable
52
+ # Number of authentication tries before locking an account.
53
+ # config.maximum_attempts = 20
54
+
55
+ # Defines which strategy will be used to unlock an account.
56
+ # :email = Sends an unlock link to the user email
57
+ # :time = Reanables login after a certain ammount of time (see :unlock_in below)
58
+ # :both = enables both strategies
59
+ # config.unlock_strategy = :both
60
+
61
+ # Time interval to unlock the account if :time is enabled as unlock_strategy.
62
+ # config.unlock_in = 1.hour
63
+
64
+ # ==> Configuration for :token_authenticatable
65
+ # Defines name of the authentication token params key
66
+ # config.token_authentication_key = :auth_token
67
+
68
+ # ==> General configuration
69
+ # Load and configure the ORM. Supports :active_record (default), :mongo_mapper
70
+ # (requires mongo_ext installed) and :data_mapper (experimental).
71
+ # require 'devise/orm/mongo_mapper'
72
+ # config.orm = :mongo_mapper
73
+
74
+ # Turn scoped views on. Before rendering "sessions/new", it will first check for
75
+ # "sessions/users/new". It's turned off by default because it's slower if you
76
+ # are using only default views.
77
+ # config.scoped_views = true
78
+
79
+ # By default, devise detects the role accessed based on the url. So whenever
80
+ # accessing "/users/sign_in", it knows you are accessing an User. This makes
81
+ # routes as "/sign_in" not possible, unless you tell Devise to use the default
82
+ # scope, setting true below.
83
+ config.use_default_scope = true
84
+
85
+ # Configure the default scope used by Devise. By default it's the first devise
86
+ # role declared in your routes.
87
+ config.default_scope = :user
88
+
89
+ # If you want to use other strategies, that are not (yet) supported by Devise,
90
+ # you can configure them inside the config.warden block. The example below
91
+ # allows you to setup OAuth, using http://github.com/roman/warden_oauth
92
+ #
93
+ # config.warden do |manager|
94
+ # manager.oauth(:twitter) do |twitter|
95
+ # twitter.consumer_secret = <YOUR CONSUMER SECRET>
96
+ # twitter.consumer_key = <YOUR CONSUMER KEY>
97
+ # twitter.options :site => 'http://twitter.com'
98
+ # end
99
+ # manager.default_strategies.unshift :twitter_oauth
100
+ # end
101
+
102
+ # Configure default_url_options if you are using dynamic segments in :path_prefix
103
+ # for devise_for.
104
+ # config.default_url_options do
105
+ # { :locale => I18n.locale }
106
+ # end
107
+
108
+ config.add_module(:approvable, :model => 'devise/approvable')
109
+ config.add_module(:approvable_email, :model => 'devise/approvable_mailer')
110
+ end
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: device-approvable 0.1.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "device-approvable"
9
+ s.version = "0.1.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Alex Egg"]
14
+ s.date = "2015-04-03"
15
+ s.description = "adds feature to devise"
16
+ s.email = "eggie5@gmail.com"
17
+ s.extra_rdoc_files = [
18
+ "README"
19
+ ]
20
+ s.files = [
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "README",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "config/initializers/devise.rb",
27
+ "device-approvable.gemspec",
28
+ "lib/approvable.rb",
29
+ "lib/approvable_mailer.rb",
30
+ "test/approvable_test.rb",
31
+ "views/devise_mailer/approval_instructions.html.erb"
32
+ ]
33
+ s.homepage = "http://github.com/eggie5/device-approvable"
34
+ s.licenses = ["MIT"]
35
+ s.rubygems_version = "2.2.1"
36
+ s.summary = "Oh so perfect"
37
+
38
+ if s.respond_to? :specification_version then
39
+ s.specification_version = 4
40
+
41
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
43
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
44
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
45
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
46
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
47
+ else
48
+ s.add_dependency(%q<shoulda>, [">= 0"])
49
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
50
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
51
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
52
+ s.add_dependency(%q<simplecov>, [">= 0"])
53
+ end
54
+ else
55
+ s.add_dependency(%q<shoulda>, [">= 0"])
56
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
57
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
58
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
59
+ s.add_dependency(%q<simplecov>, [">= 0"])
60
+ end
61
+ end
62
+
@@ -0,0 +1,174 @@
1
+ module Devise
2
+ module Models
3
+ module Approvable
4
+ # extend ActiveSupport::Concern #RAILS 3
5
+ include Devise::Models::Activatable
6
+
7
+ def self.included(base)
8
+ base.class_eval do
9
+ extend ClassMethods
10
+
11
+ before_create :generate_approval_token, :if => :approval_required?
12
+ # after_create :send_approval_instructions unless approved?
13
+ end
14
+ end
15
+
16
+ # Confirm a user by setting it's confirmed_at to actual time. If the user
17
+ # is already confirmed, add en error to email field
18
+ def confirm!
19
+ unless_confirmed do
20
+ self.confirmation_token = nil
21
+ self.confirmed_at = Time.now
22
+ save(false)
23
+ end
24
+ end
25
+
26
+ # Verifies whether a user is confirmed or not
27
+ def confirmed?
28
+ !new_record? && !confirmed_at.nil?
29
+ end
30
+
31
+ # Send confirmation instructions by email
32
+ def send_confirmation_instructions
33
+ generate_confirmation_token if self.confirmation_token.nil?
34
+ ::DeviseMailer.deliver_confirmation_instructions(self)
35
+ end
36
+
37
+ # Resend confirmation token. This method does not need to generate a new token.
38
+ def resend_confirmation_token
39
+ unless_confirmed { send_confirmation_instructions }
40
+ end
41
+
42
+ # Overwrites active? from Devise::Models::Activatable for confirmation
43
+ # by verifying whether an user is active to sign in or not. If the user
44
+ # is already confirmed, it should never be blocked. Otherwise we need to
45
+ # calculate if the confirm time has not expired for this user.
46
+ def active?
47
+ super && (!confirmation_required? || confirmed? || confirmation_period_valid?)
48
+ end
49
+
50
+ # The message to be shown if the account is inactive.
51
+ def inactive_message
52
+ !confirmed? ? :unconfirmed : super
53
+ end
54
+
55
+ # If you don't want confirmation to be sent on create, neither a code
56
+ # to be generated, call skip_confirmation!
57
+ def skip_confirmation!
58
+ self.confirmed_at = Time.now
59
+ @skip_confirmation = true
60
+ end
61
+
62
+ def skip_confirm_and_approve!
63
+ skip_confirmation!
64
+ skip_approval!
65
+ end
66
+
67
+ def approve!
68
+ self.is_approved = true
69
+ self.approval_token = nil
70
+ send_confirmation_instructions
71
+ save(:validate => false)
72
+ end
73
+
74
+ # Verifies whether a user is confirmed or not
75
+ def approved?
76
+ self.is_approved
77
+ end
78
+
79
+ def skip_approval!
80
+ self.is_approved = true
81
+ @skip_approval = true
82
+ end
83
+
84
+ # Send confirmation instructions by email
85
+ def send_approval_instructions
86
+ generate_approval_token if self.approval_token.nil?
87
+ ::DeviseMailer.deliver_approval_instructions(self)
88
+ end
89
+
90
+ protected
91
+
92
+ # Callback to overwrite if confirmation is required or not.
93
+ def confirmation_required?
94
+ !@skip_confirmation
95
+ end
96
+
97
+ def approval_required?
98
+ !@skip_approval
99
+ end
100
+
101
+ # Checks if the confirmation for the user is within the limit time.
102
+ # We do this by calculating if the difference between today and the
103
+ # confirmation sent date does not exceed the confirm in time configured.
104
+ # Confirm_in is a model configuration, must always be an integer value.
105
+ #
106
+ # Example:
107
+ #
108
+ # # confirm_within = 1.day and confirmation_sent_at = today
109
+ # confirmation_period_valid? # returns true
110
+ #
111
+ # # confirm_within = 5.days and confirmation_sent_at = 4.days.ago
112
+ # confirmation_period_valid? # returns true
113
+ #
114
+ # # confirm_within = 5.days and confirmation_sent_at = 5.days.ago
115
+ # confirmation_period_valid? # returns false
116
+ #
117
+ # # confirm_within = 0.days
118
+ # confirmation_period_valid? # will always return false
119
+ #
120
+ def confirmation_period_valid?
121
+ confirmation_sent_at && confirmation_sent_at.utc >= self.class.confirm_within.ago
122
+ end
123
+
124
+ # Checks whether the record is confirmed or not, yielding to the block
125
+ # if it's already confirmed, otherwise adds an error to email.
126
+ def unless_confirmed
127
+ unless confirmed?
128
+ yield
129
+ else
130
+ self.class.add_error_on(self, :email, :already_confirmed)
131
+ false
132
+ end
133
+ end
134
+
135
+ # Generates a new random token for confirmation, and stores the time
136
+ # this token is being generated
137
+ def generate_confirmation_token
138
+ self.confirmed_at = nil
139
+ self.confirmation_token = Devise.friendly_token
140
+ self.confirmation_sent_at = Time.now.utc
141
+ end
142
+
143
+ def generate_approval_token
144
+ self.is_approved = false
145
+ self.approval_token = Devise.friendly_token
146
+ self.approval_sent_at = Time.now.utc
147
+ end
148
+
149
+ module ClassMethods
150
+ # Attempt to find a user by it's email. If a record is found, send new
151
+ # confirmation instructions to it. If not user is found, returns a new user
152
+ # with an email not found error.
153
+ # Options must contain the user email
154
+ def send_confirmation_instructions(attributes={})
155
+ confirmable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
156
+ confirmable.resend_confirmation_token unless confirmable.new_record?
157
+ confirmable
158
+ end
159
+
160
+ # Find a user by it's confirmation token and try to confirm it.
161
+ # If no user is found, returns a new user with an error.
162
+ # If the user is already confirmed, create an error for the user
163
+ # Options must have the confirmation_token
164
+ def confirm_by_token(confirmation_token)
165
+ confirmable = find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
166
+ confirmable.confirm! unless confirmable.new_record?
167
+ confirmable
168
+ end
169
+
170
+ Devise::Models.config(self, :confirm_within)
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,11 @@
1
+ Devise.module_eval {
2
+ mattr_accessor :approval_recepient
3
+ @@approval_recepient = nil
4
+ }
5
+
6
+ DeviseMailer.module_eval {
7
+ def approval_instructions(record)
8
+ setup_mail(record, :approval_instructions)
9
+ recipients Devise.approval_recepient
10
+ end
11
+ }
@@ -0,0 +1,245 @@
1
+ require 'test/test_helper'
2
+ require 'test/unit/helpers/approvable_helper_test'
3
+
4
+ class ApprovableTest < ActiveSupport::TestCase
5
+
6
+ def setup
7
+ setup_mailer
8
+ end
9
+
10
+ test 'should never generate the same confirmation token for different users' do
11
+ confirmation_tokens = []
12
+ 3.times do
13
+ token = create_user.send_confirmation_instructions
14
+ assert !confirmation_tokens.include?(token)
15
+ confirmation_tokens << token
16
+ end
17
+ end
18
+
19
+ test 'should confirm a user by updating confirmed at' do
20
+ user = create_user
21
+ assert_nil user.confirmed_at
22
+ assert user.confirm!
23
+ assert_not_nil user.confirmed_at
24
+ end
25
+
26
+ test 'should clear confirmation token while confirming a user' do
27
+ user = create_user
28
+ user.confirm!
29
+ assert_nil user.confirmation_token
30
+ end
31
+
32
+ test 'should verify whether a user is confirmed or not' do
33
+ assert_not new_user.confirmed?
34
+ user = create_user
35
+ assert_not user.confirmed?
36
+ user.confirm!
37
+ assert user.confirmed?
38
+ end
39
+
40
+ test 'should not confirm a user already confirmed' do
41
+ user = create_user
42
+ assert user.confirm!
43
+ assert_nil user.errors[:email]
44
+
45
+ assert_not user.confirm!
46
+ assert_match /already confirmed/, user.errors[:email]
47
+ end
48
+
49
+ test 'should return a new record with errors when a invalid token is given' do
50
+ confirmed_user = User.confirm_by_token('invalid_confirmation_token')
51
+ assert confirmed_user.new_record?
52
+ assert_match /invalid/, confirmed_user.errors[:confirmation_token]
53
+ end
54
+
55
+ test 'should return a new record with errors when a blank token is given' do
56
+ confirmed_user = User.confirm_by_token('')
57
+ assert confirmed_user.new_record?
58
+ assert_match /blank/, confirmed_user.errors[:confirmation_token]
59
+ end
60
+
61
+ test 'should authenticate a confirmed user' do
62
+ user = create_user
63
+ user.confirm!
64
+ authenticated_user = User.authenticate(:email => user.email, :password => user.password)
65
+ assert_equal authenticated_user, user
66
+ end
67
+
68
+ test 'should not send confirmation when trying to save an invalid user' do
69
+ assert_email_not_sent do
70
+ user = new_user
71
+ user.stubs(:valid?).returns(false)
72
+ user.save
73
+ end
74
+ end
75
+
76
+ test 'should not generate a new token neither send e-mail if skip_confirmation! is invoked' do
77
+ user = new_user
78
+ user.skip_confirmation!
79
+
80
+ assert_email_not_sent do
81
+ user.save!
82
+ assert_nil user.confirmation_token
83
+ assert_not_nil user.confirmed_at
84
+ end
85
+ end
86
+
87
+ test 'should find a user to send confirmation instructions' do
88
+ user = create_user
89
+ confirmation_user = User.send_confirmation_instructions(:email => user.email)
90
+ assert_equal confirmation_user, user
91
+ end
92
+
93
+ test 'should return a new user if no email was found' do
94
+ confirmation_user = User.send_confirmation_instructions(:email => "invalid@email.com")
95
+ assert confirmation_user.new_record?
96
+ end
97
+
98
+ test 'should add error to new user email if no email was found' do
99
+ confirmation_user = User.send_confirmation_instructions(:email => "invalid@email.com")
100
+ assert confirmation_user.errors[:email]
101
+ assert_equal 'not found', confirmation_user.errors[:email]
102
+ end
103
+
104
+ test 'should send email instructions for the user confirm it\'s email' do
105
+ user = create_user
106
+ assert_email_sent do
107
+ User.send_confirmation_instructions(:email => user.email)
108
+ end
109
+ end
110
+
111
+ test 'should always have confirmation token when email is sent' do
112
+ user = new_user
113
+ user.instance_eval { def confirmation_required?; false end }
114
+ user.save
115
+ user.send_confirmation_instructions
116
+ assert_not_nil user.confirmation_token
117
+ end
118
+
119
+ test 'should not resend email instructions if the user change his email' do
120
+ user = create_user
121
+ user.email = 'new_test@example.com'
122
+ assert_email_not_sent do
123
+ user.save!
124
+ end
125
+ end
126
+
127
+ test 'should not reset confirmation status or token when updating email' do
128
+ user = create_user
129
+ user.confirm!
130
+ user.email = 'new_test@example.com'
131
+ user.save!
132
+
133
+ user.reload
134
+ assert user.confirmed?
135
+ assert_nil user.confirmation_token
136
+ end
137
+
138
+ test 'should not be able to send instructions if the user is already confirmed' do
139
+ user = create_user
140
+ user.confirm!
141
+ assert_not user.resend_confirmation_token
142
+ assert user.confirmed?
143
+ assert_equal 'already confirmed', user.errors[:email]
144
+ end
145
+
146
+ test 'confirm time should fallback to devise confirm in default configuration' do
147
+ swap Devise, :confirm_within => 1.day do
148
+ user = new_user
149
+ user.confirmation_sent_at = 2.days.ago
150
+ assert_not user.active?
151
+
152
+ Devise.confirm_within = 3.days
153
+ assert user.active?
154
+ end
155
+ end
156
+
157
+ test 'should be active when confirmation sent at is not overpast' do
158
+ swap Devise, :confirm_within => 5.days do
159
+ Devise.confirm_within = 5.days
160
+ user = create_user
161
+
162
+ user.confirmation_sent_at = 4.days.ago
163
+ assert user.active?
164
+
165
+ user.confirmation_sent_at = 5.days.ago
166
+ assert_not user.active?
167
+ end
168
+ end
169
+
170
+ test 'should be active when already confirmed' do
171
+ user = create_user
172
+ assert_not user.confirmed?
173
+ assert_not user.active?
174
+
175
+ user.confirm!
176
+ assert user.confirmed?
177
+ assert user.active?
178
+ end
179
+
180
+ test 'should not be active when confirm in is zero' do
181
+ Devise.confirm_within = 0.days
182
+ user = create_user
183
+ user.confirmation_sent_at = Date.today
184
+ assert_not user.reload.active?
185
+ end
186
+
187
+ test 'should not be active without confirmation' do
188
+ user = create_user
189
+ user.confirmation_sent_at = nil
190
+ user.save
191
+ assert_not user.reload.active?
192
+ end
193
+
194
+ test 'should be active without confirmation when confirmation is not required' do
195
+ user = create_user
196
+ user.instance_eval { def confirmation_required?; false end }
197
+ user.confirmation_sent_at = nil
198
+ user.save
199
+ assert user.reload.active?
200
+ end
201
+
202
+ # Approvable Tests
203
+
204
+ test 'should generate approval token after creating a record' do
205
+ assert_nil new_user.approval_token
206
+ assert_not_nil create_user.approval_token
207
+ end
208
+
209
+ test 'should clear approval token after approving a user' do
210
+ user = create_user
211
+ user.approve!
212
+ assert_nil user.approval_token
213
+ end
214
+
215
+ test 'should verify whether a user is approved or not' do
216
+ assert_not new_user.approved?
217
+ user = create_user
218
+ assert_not user.approved?
219
+ user.approve!
220
+ assert user.approved?
221
+ end
222
+
223
+ test 'should not generate a new token neither send e-mail if skip_approval! is invoked' do
224
+ user = new_user
225
+ user.skip_approval!
226
+
227
+ assert_email_not_sent do
228
+ user.save!
229
+ assert_nil user.approval_token
230
+ end
231
+ end
232
+
233
+ test 'should not generate a new token neither send e-mail if skip_confirm_and_approve! is invoked' do
234
+ user = new_user
235
+ user.skip_confirm_and_approve!
236
+
237
+ assert_email_not_sent do
238
+ user.save!
239
+ assert_nil user.confirmation_token
240
+ assert_nil user.approval_token
241
+ assert user.approved?
242
+ assert_not_nil user.confirmed_at
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,11 @@
1
+ <p>Someone has registered for a membership.</p>
2
+
3
+ <p>Details:
4
+ <%= "<br />First Name: #{@resource.first_name}" if !@resource.first_name.nil? %>
5
+ <%= "<br />Last Name: #{@resource.last_name}" if !@resource.last_name.nil? %>
6
+ <%= "<br />E-Mail: #{@resource.email}" if !@resource.email.nil? %>
7
+ <%= "<br />Phone Number: #{@resource.phone}" if !@resource.phone.nil? %>
8
+ <%= "<br />Bio: #{@resource.bio}" if !@resource.bio.nil? %>
9
+
10
+ <p>If you would like to approve this person click the following link. Clicking the link will approve the new user and send the user a confirmation email.</p>
11
+ <p><%= link_to "Approve account for #{@resource.email} #{approvals_url(@resource.approval_token)}", approvals_url(@resource.approval_token) %></p>
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: device-approvable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Egg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: shoulda
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jeweler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: adds feature to devise
84
+ email: eggie5@gmail.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files:
88
+ - README
89
+ files:
90
+ - Gemfile
91
+ - Gemfile.lock
92
+ - README
93
+ - Rakefile
94
+ - VERSION
95
+ - config/initializers/devise.rb
96
+ - device-approvable.gemspec
97
+ - lib/approvable.rb
98
+ - lib/approvable_mailer.rb
99
+ - test/approvable_test.rb
100
+ - views/devise_mailer/approval_instructions.html.erb
101
+ homepage: http://github.com/eggie5/device-approvable
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.2.1
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Oh so perfect
125
+ test_files: []