avocado 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +4 -0
- data/app/controllers/avocado/affirmations_controller.rb +51 -0
- data/app/controllers/avocado/base_controller.rb +10 -0
- data/app/controllers/avocado/emails_controller.rb +48 -0
- data/app/controllers/avocado/events_controller.rb +9 -0
- data/app/controllers/avocado/passwords_controller.rb +34 -0
- data/app/views/avocado/affirmations/new.html.erb +14 -0
- data/app/views/avocado/emails/edit.html.erb +20 -0
- data/app/views/avocado/events/_event.html.erb +6 -0
- data/app/views/avocado/events/index.html.erb +17 -0
- data/app/views/avocado/mailer/email_affirmation.text.erb +3 -1
- data/app/views/avocado/mailer/email_verification.text.erb +1 -1
- data/app/views/avocado/mailer/password_reset.text.erb +1 -1
- data/app/views/avocado/passwords/edit.html.erb +16 -0
- data/app/views/avocado/recoveries/edit.html.erb +2 -2
- data/app/views/avocado/recoveries/new.html.erb +2 -2
- data/app/views/avocado/registrations/new.html.erb +1 -1
- data/app/views/avocado/sessions/new.html.erb +1 -1
- data/config/routes.rb +4 -0
- data/lib/avocado/current.rb +10 -8
- data/lib/avocado/event.rb +32 -0
- data/lib/avocado/session.rb +3 -0
- data/lib/avocado/session_callbacks.rb +34 -0
- data/lib/avocado/user.rb +10 -3
- data/lib/avocado/user_callbacks.rb +45 -0
- data/lib/avocado/user_validations.rb +22 -0
- data/lib/avocado/version.rb +1 -1
- data/lib/avocado.rb +4 -2
- metadata +15 -4
- data/lib/avocado/user_email.rb +0 -13
- data/lib/avocado/user_password.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a530ebf9605c2bb861d2da09da546513e68c4f647fc97c80686e07b32985cabe
|
4
|
+
data.tar.gz: 3be481be5c31ce2ee3bb1ea1a2d796bb7f8cbe850f7ccf2de6f296384a656bb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf3320eb985cc65c05c2da2d007697b4b9016d9a85f7ebebbd0735d744d7f8ca77096d86182c6761b63ea6f51f4b942a3c2dd363bb102ccc4ed53da6f5702c4f
|
7
|
+
data.tar.gz: f0b021b9e0f3433f2034e5cccdc751a446b50bc870474376e1a39b84e973bbabfaef95b59d96f60986bbddc7695afe88b860bd2d1568f991a17b3b654d7f3995
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.0] - 2023-07-21
|
4
|
+
|
5
|
+
- Add controller for "passwordless" email-link sign-in
|
6
|
+
- Add event class to log user auth events
|
7
|
+
- Add user-facing email and password edit pages
|
8
|
+
- Add various event logging callbacks
|
9
|
+
- Sign out all non current sessions when password changes
|
10
|
+
|
3
11
|
## [0.4.0] - 2023-07-19
|
4
12
|
|
5
13
|
- Convert the `Avocado::Mailer` module into a class
|
data/README.md
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
class AffirmationsController < BaseController
|
5
|
+
skip_before_action :authenticate
|
6
|
+
|
7
|
+
before_action :set_user, only: :show
|
8
|
+
before_action :verify_user, only: :create
|
9
|
+
|
10
|
+
def new
|
11
|
+
end
|
12
|
+
|
13
|
+
def show
|
14
|
+
sign_in(@user)
|
15
|
+
redirect_to(root_path, notice: "Signed in successfully")
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
send_affirmation_email
|
20
|
+
redirect_to new_session_path, notice: "Check your email for sign in instructions"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def set_user
|
26
|
+
@user = user_from_signed_affirmation_token
|
27
|
+
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
28
|
+
redirect_to new_affirmation_path, alert: "That sign in link is invalid"
|
29
|
+
end
|
30
|
+
|
31
|
+
def user_from_signed_affirmation_token
|
32
|
+
::User.find_by_token_for!(:email_affirmation, params[:id])
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_user
|
36
|
+
unless user_from_params_email
|
37
|
+
redirect_to new_affirmation_path, alert: "You can't sign in until you verify your email"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_affirmation_email
|
42
|
+
mailer_for(user_from_params_email)
|
43
|
+
.email_affirmation
|
44
|
+
.deliver_later
|
45
|
+
end
|
46
|
+
|
47
|
+
def user_from_params_email
|
48
|
+
::User.verified.find_by(email: params[:email])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -4,6 +4,16 @@ module Avocado
|
|
4
4
|
class BaseController < ApplicationController
|
5
5
|
private
|
6
6
|
|
7
|
+
def verify_password_challenge
|
8
|
+
unless current_user.authenticate(params_password_challenge)
|
9
|
+
redirect_back alert: "Password challenge failed.", fallback_location: root_path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def params_password_challenge
|
14
|
+
params.dig(:user, :password_challenge)
|
15
|
+
end
|
16
|
+
|
7
17
|
def mailer_for(user)
|
8
18
|
Avocado::Mailer.with(user: user)
|
9
19
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
class EmailsController < BaseController
|
5
|
+
PERMITTED_PARAMS = [:email]
|
6
|
+
|
7
|
+
before_action :set_user
|
8
|
+
before_action :verify_password_challenge, only: :update
|
9
|
+
|
10
|
+
def edit
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
if @user.update(user_params)
|
15
|
+
process_email_update
|
16
|
+
else
|
17
|
+
render :edit, status: :unprocessable_entity
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def set_user
|
24
|
+
@user = current_user
|
25
|
+
end
|
26
|
+
|
27
|
+
def user_params
|
28
|
+
params
|
29
|
+
.require(:user)
|
30
|
+
.permit(PERMITTED_PARAMS)
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_email_update
|
34
|
+
if @user.email_previously_changed?
|
35
|
+
resend_email_verification
|
36
|
+
redirect_to root_path, notice: "Your email has been changed"
|
37
|
+
else
|
38
|
+
redirect_to root_path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def resend_email_verification
|
43
|
+
mailer_for(@user)
|
44
|
+
.email_verification
|
45
|
+
.deliver_later
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
class PasswordsController < BaseController
|
5
|
+
PERMITTED_PARAMS = [:password, :password_confirmation, :password_challenge]
|
6
|
+
|
7
|
+
before_action :set_user
|
8
|
+
before_action :verify_password_challenge, only: :update
|
9
|
+
|
10
|
+
def edit
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
if @user.update(user_params)
|
15
|
+
redirect_to root_path, notice: "Your password has been changed"
|
16
|
+
else
|
17
|
+
render :edit, status: :unprocessable_entity
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def set_user
|
24
|
+
@user = current_user
|
25
|
+
end
|
26
|
+
|
27
|
+
def user_params
|
28
|
+
params
|
29
|
+
.require(:user)
|
30
|
+
.permit(PERMITTED_PARAMS)
|
31
|
+
.with_defaults(password_challenge: "")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<h2>
|
2
|
+
Sign in without password
|
3
|
+
</h2>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
<%= link_to "Reset your password", new_recovery_path %>
|
7
|
+
</p>
|
8
|
+
|
9
|
+
<%= form_with url: affirmations_path do |form| %>
|
10
|
+
<%= form.label :email %>
|
11
|
+
<%= form.email_field :email, autofocus: true, autocomplete: "email", required: true %>
|
12
|
+
|
13
|
+
<%= form.button "Submit", name: nil %>
|
14
|
+
<% end -%>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h2>
|
2
|
+
Change your email address
|
3
|
+
</h2>
|
4
|
+
|
5
|
+
<% if current_user.verified? %>
|
6
|
+
<p>Your email address is verified.</p>
|
7
|
+
<% else %>
|
8
|
+
<p>Your email address is not verified. Check your email and follow the instructions to confirm it's your email address.</p>
|
9
|
+
<p><%= button_to "Re-send verification email", verifications_path %></p>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<%= form_with model: @user, url: email_path, method: :patch do |form| %>
|
13
|
+
<%= form.label :email %>
|
14
|
+
<%= form.email_field :email, autocomplete: "email", required: true %>
|
15
|
+
|
16
|
+
<%= form.label :password_challenge, "Current password" %>
|
17
|
+
<%= form.password_field :password_challenge, autocomplete: "current-password", required: true %>
|
18
|
+
|
19
|
+
<%= form.button "Submit", name: nil %>
|
20
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h2>
|
2
|
+
Events
|
3
|
+
</h2>
|
4
|
+
|
5
|
+
<table id="events">
|
6
|
+
<thead>
|
7
|
+
<tr>
|
8
|
+
<th scope="col">Action</th>
|
9
|
+
<th scope="col">Created</th>
|
10
|
+
<th scope="col">User Agent</th>
|
11
|
+
<th scope="col">IP Address</th>
|
12
|
+
</tr>
|
13
|
+
</thead>
|
14
|
+
<tbody>
|
15
|
+
<%= render @events %>
|
16
|
+
</tbody>
|
17
|
+
</table>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<h2>
|
2
|
+
Change your password
|
3
|
+
</h2>
|
4
|
+
|
5
|
+
<%= form_with model: @user, url: password_path, method: :patch do |form| %>
|
6
|
+
<%= form.label :password_challenge, "Current password" %>
|
7
|
+
<%= form.password_field :password_challenge, autocomplete: "current-password", required: true %>
|
8
|
+
|
9
|
+
<%= form.label :password %>
|
10
|
+
<%= form.password_field :password, autocomplete: "new-password", required: true %>
|
11
|
+
|
12
|
+
<%= form.label :password_confirmation %>
|
13
|
+
<%= form.password_field :password_confirmation, autocomplete: "new-password", required: true %>
|
14
|
+
|
15
|
+
<%= form.button "Submit", name: nil %>
|
16
|
+
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<h2>
|
2
|
-
|
2
|
+
Change your password
|
3
3
|
</h2>
|
4
4
|
|
5
5
|
<p>
|
@@ -13,5 +13,5 @@
|
|
13
13
|
<%= form.label :password_confirmation %>
|
14
14
|
<%= form.password_field :password_confirmation, autocomplete: "new-password", required: true %>
|
15
15
|
|
16
|
-
<%= form.button "
|
16
|
+
<%= form.button "Submit", name: nil %>
|
17
17
|
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<h2>
|
2
|
-
|
2
|
+
Reset your password
|
3
3
|
</h2>
|
4
4
|
|
5
5
|
<p>
|
@@ -10,5 +10,5 @@
|
|
10
10
|
<%= form.label :email %>
|
11
11
|
<%= form.email_field :email, autofocus: true, autocomplete: "email", required: true %>
|
12
12
|
|
13
|
-
<%= form.button "
|
13
|
+
<%= form.button "Submit", name: nil %>
|
14
14
|
<% end -%>
|
@@ -11,5 +11,5 @@
|
|
11
11
|
<%= form.email_field :email, autofocus: true, autocomplete: "email", required: true %>
|
12
12
|
<%= form.label :password %>
|
13
13
|
<%= form.password_field :password, autocomplete: "current-password", required: true %>
|
14
|
-
<%= form.button "
|
14
|
+
<%= form.button "Submit", name: nil %>
|
15
15
|
<% end -%>
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
scope module: :avocado do
|
3
|
+
resource :email, only: %i[edit update]
|
4
|
+
resource :password, only: %i[edit update]
|
5
|
+
resources :affirmations, only: %i[new show create]
|
6
|
+
resources :events, only: %i[index]
|
3
7
|
resources :recoveries, only: %i[new create edit update]
|
4
8
|
resources :registrations, only: %i[new create]
|
5
9
|
resources :sessions, only: %i[index new create destroy]
|
data/lib/avocado/current.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
:
|
6
|
-
|
7
|
-
|
3
|
+
module Avocado
|
4
|
+
class Current < ActiveSupport::CurrentAttributes
|
5
|
+
attribute :session,
|
6
|
+
:user,
|
7
|
+
:user_agent,
|
8
|
+
:ip_address
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def session=(session)
|
11
|
+
super
|
12
|
+
self.user = session.user
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
module Event
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
VALID_ACTIONS = [
|
8
|
+
"email:update",
|
9
|
+
"email:verified",
|
10
|
+
"password:update",
|
11
|
+
"session:create",
|
12
|
+
"session:destroy"
|
13
|
+
]
|
14
|
+
|
15
|
+
included do
|
16
|
+
belongs_to :user
|
17
|
+
|
18
|
+
scope :newest_first, -> { order(created_at: :desc) }
|
19
|
+
|
20
|
+
validates :action, inclusion: VALID_ACTIONS
|
21
|
+
|
22
|
+
before_create :capture_request_details
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def capture_request_details
|
28
|
+
self.user_agent = Current.user_agent
|
29
|
+
self.ip_address = Current.ip_address
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/avocado/session.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
module SessionCallbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
after_create :record_activity_create
|
9
|
+
|
10
|
+
after_destroy :record_activity_destroy
|
11
|
+
|
12
|
+
before_create :capture_request_details
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def record_activity_create
|
18
|
+
create_user_event "session:create"
|
19
|
+
end
|
20
|
+
|
21
|
+
def record_activity_destroy
|
22
|
+
create_user_event "session:destroy"
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_user_event(action)
|
26
|
+
user.events.create! action: action
|
27
|
+
end
|
28
|
+
|
29
|
+
def capture_request_details
|
30
|
+
self.user_agent = Current.user_agent
|
31
|
+
self.ip_address = Current.ip_address
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/avocado/user.rb
CHANGED
@@ -5,14 +5,21 @@ module Avocado
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
include
|
8
|
+
include UserCallbacks
|
9
9
|
include UserTokens
|
10
|
-
include
|
10
|
+
include UserValidations
|
11
11
|
|
12
|
-
|
12
|
+
has_secure_password
|
13
|
+
|
14
|
+
with_options dependent: :destroy do
|
15
|
+
has_many :events
|
16
|
+
has_many :sessions
|
17
|
+
end
|
13
18
|
|
14
19
|
scope :newest_first, -> { order(created_at: :desc) }
|
15
20
|
scope :verified, -> { where(verified: true) }
|
21
|
+
|
22
|
+
normalizes :email, with: ->(email) { email.downcase.strip }
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
module UserCallbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
with_options if: :password_digest_previously_changed? do
|
9
|
+
after_update :destroy_non_current_sessions
|
10
|
+
after_update :record_activity_password_update
|
11
|
+
end
|
12
|
+
|
13
|
+
after_update :record_activity_email_update, if: :email_previously_changed?
|
14
|
+
after_update :record_activity_email_verified, if: %i[verified_previously_changed? verified?]
|
15
|
+
|
16
|
+
before_validation :remove_email_verification, if: :email_changed?, on: :update
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def record_activity_password_update
|
22
|
+
create_event "password:update"
|
23
|
+
end
|
24
|
+
|
25
|
+
def record_activity_email_update
|
26
|
+
create_event "email:update"
|
27
|
+
end
|
28
|
+
|
29
|
+
def record_activity_email_verified
|
30
|
+
create_event "email:verified"
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_event(action)
|
34
|
+
events.create! action: action
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_email_verification
|
38
|
+
self.verified = false
|
39
|
+
end
|
40
|
+
|
41
|
+
def destroy_non_current_sessions
|
42
|
+
sessions.non_current.destroy_all
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Avocado
|
4
|
+
module UserValidations
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
PASSWORD_FORMAT = /\A(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*\z/x
|
8
|
+
PASSWORD_MINIMUM_LENGTH = 8
|
9
|
+
|
10
|
+
included do
|
11
|
+
validates :email,
|
12
|
+
presence: true,
|
13
|
+
uniqueness: true,
|
14
|
+
format: {with: URI::MailTo::EMAIL_REGEXP}
|
15
|
+
|
16
|
+
validates :password,
|
17
|
+
format: {with: PASSWORD_FORMAT},
|
18
|
+
length: {minimum: PASSWORD_MINIMUM_LENGTH},
|
19
|
+
allow_nil: true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/avocado/version.rb
CHANGED
data/lib/avocado.rb
CHANGED
@@ -7,10 +7,12 @@ module Avocado
|
|
7
7
|
|
8
8
|
autoload :Authentication, "avocado/authentication"
|
9
9
|
autoload :Current, "avocado/current"
|
10
|
+
autoload :Event, "avocado/event"
|
10
11
|
autoload :Mailer, "avocado/mailer"
|
11
12
|
autoload :Session, "avocado/session"
|
13
|
+
autoload :SessionCallbacks, "avocado/session_callbacks"
|
12
14
|
autoload :User, "avocado/user"
|
13
|
-
autoload :
|
15
|
+
autoload :UserCallbacks, "avocado/user_callbacks"
|
14
16
|
autoload :UserTokens, "avocado/user_tokens"
|
15
|
-
autoload :
|
17
|
+
autoload :UserValidations, "avocado/user_validations"
|
16
18
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avocado
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Jankowski
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bcrypt
|
@@ -80,14 +80,23 @@ files:
|
|
80
80
|
- LICENSE.txt
|
81
81
|
- README.md
|
82
82
|
- Rakefile
|
83
|
+
- app/controllers/avocado/affirmations_controller.rb
|
83
84
|
- app/controllers/avocado/base_controller.rb
|
85
|
+
- app/controllers/avocado/emails_controller.rb
|
86
|
+
- app/controllers/avocado/events_controller.rb
|
87
|
+
- app/controllers/avocado/passwords_controller.rb
|
84
88
|
- app/controllers/avocado/recoveries_controller.rb
|
85
89
|
- app/controllers/avocado/registrations_controller.rb
|
86
90
|
- app/controllers/avocado/sessions_controller.rb
|
87
91
|
- app/controllers/avocado/verifications_controller.rb
|
92
|
+
- app/views/avocado/affirmations/new.html.erb
|
93
|
+
- app/views/avocado/emails/edit.html.erb
|
94
|
+
- app/views/avocado/events/_event.html.erb
|
95
|
+
- app/views/avocado/events/index.html.erb
|
88
96
|
- app/views/avocado/mailer/email_affirmation.text.erb
|
89
97
|
- app/views/avocado/mailer/email_verification.text.erb
|
90
98
|
- app/views/avocado/mailer/password_reset.text.erb
|
99
|
+
- app/views/avocado/passwords/edit.html.erb
|
91
100
|
- app/views/avocado/recoveries/edit.html.erb
|
92
101
|
- app/views/avocado/recoveries/new.html.erb
|
93
102
|
- app/views/avocado/registrations/new.html.erb
|
@@ -100,12 +109,14 @@ files:
|
|
100
109
|
- lib/avocado/authentication.rb
|
101
110
|
- lib/avocado/current.rb
|
102
111
|
- lib/avocado/engine.rb
|
112
|
+
- lib/avocado/event.rb
|
103
113
|
- lib/avocado/mailer.rb
|
104
114
|
- lib/avocado/session.rb
|
115
|
+
- lib/avocado/session_callbacks.rb
|
105
116
|
- lib/avocado/user.rb
|
106
|
-
- lib/avocado/
|
107
|
-
- lib/avocado/user_password.rb
|
117
|
+
- lib/avocado/user_callbacks.rb
|
108
118
|
- lib/avocado/user_tokens.rb
|
119
|
+
- lib/avocado/user_validations.rb
|
109
120
|
- lib/avocado/version.rb
|
110
121
|
- sig/avocado.rbs
|
111
122
|
homepage: https://github.com/tcuwp/avocado
|
data/lib/avocado/user_email.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Avocado
|
4
|
-
module UserEmail
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
validates :email, presence: true, uniqueness: true, format: {with: URI::MailTo::EMAIL_REGEXP}
|
9
|
-
|
10
|
-
normalizes :email, with: ->(email) { email.downcase.strip }
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Avocado
|
4
|
-
module UserPassword
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
REQUIRED_FORMAT = /\A(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).*\z/x
|
8
|
-
REQUIRED_LENGTH = 8
|
9
|
-
|
10
|
-
included do
|
11
|
-
has_secure_password
|
12
|
-
|
13
|
-
validates :password, format: {with: REQUIRED_FORMAT}, length: {minimum: REQUIRED_LENGTH}, allow_nil: true
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|