Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Milestone 9: add devise #9

Merged
merged 22 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
25c2beb
Feat: Add devise and all its required files
ITurres Dec 13, 2023
fe3b5eb
feat: Configure ApplicationController for Devise auth and param sanit…
ITurres Dec 13, 2023
1c11064
chore: update 'schema.rb' with new divese migrations
ITurres Dec 13, 2023
6fbd91a
Add new layout partial 'navbar'
ITurres Dec 13, 2023
11edc95
feat: render 'lnavbar' partial on 'application' layout
ITurres Dec 13, 2023
974c1a2
feat: added devise attributes for the user model
demesameneshoa Dec 13, 2023
f83a2c9
refactor: users#show view to accomodate the devise users data
demesameneshoa Dec 13, 2023
9b51d00
feat: modified development environment to allow localhost on mailing url
demesameneshoa Dec 13, 2023
9b7736b
Add devise and user association on routes
demesameneshoa Dec 13, 2023
29b1c7c
feat: update all devise views and links markup and styling
ITurres Dec 13, 2023
8ee0ff7
feat: Add 'sign-out' btn to 'navbar' partial
ITurres Dec 13, 2023
e5628a9
Add new shared partial 'back_button'
ITurres Dec 13, 2023
8e0a577
remove: 'sign-out' btn from 'user#show' view
ITurres Dec 13, 2023
4752389
feat: Add 'user#set_default_photo' to dynamic add user photos when si…
ITurres Dec 13, 2023
6515a96
styles: modify and add bootstrap classes to 'user_card' partial
ITurres Dec 13, 2023
edfc473
styles: modify and add bootstrap classes to 'user#show' view
ITurres Dec 13, 2023
3f08e25
linters: resolve rubocop offenses on 'user' model
ITurres Dec 13, 2023
f167613
Docs: Update 'README.md' check complete another future-feature
ITurres Dec 13, 2023
605a93c
feat: Enable 'confirmable' and run confirmable to devise
ITurres Dec 13, 2023
36f5324
chore: regenerate 'schema' with confirmable entries
ITurres Dec 13, 2023
9f4adb1
feat: update 'confirmations#new' view and 'devise/shared/links' partial
ITurres Dec 13, 2023
08a97a1
linters: resolve doublequoted ofenses
ITurres Dec 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,5 @@ group :test do
gem 'capybara'
gem 'selenium-webdriver'
end

gem 'devise', '~> 4.9'
14 changes: 14 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ GEM
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
base64 (0.1.1)
bcrypt (3.1.20)
bigdecimal (3.1.4)
bindex (0.8.1)
bootsnap (1.17.0)
Expand All @@ -100,6 +101,12 @@ GEM
debug (1.8.0)
irb (>= 1.5.0)
reline (>= 0.3.1)
devise (4.9.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
diff-lcs (1.5.0)
drb (2.2.0)
ruby2_keywords
Expand Down Expand Up @@ -155,6 +162,7 @@ GEM
nio4r (2.7.0)
nokogiri (1.15.5-x86_64-linux)
racc (~> 1.4)
orm_adapter (0.5.0)
parallel (1.23.0)
parser (3.2.2.4)
ast (~> 2.4.1)
Expand Down Expand Up @@ -214,6 +222,9 @@ GEM
regexp_parser (2.8.3)
reline (0.4.1)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.6)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
Expand Down Expand Up @@ -274,6 +285,8 @@ GEM
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
Expand All @@ -295,6 +308,7 @@ DEPENDENCIES
bootsnap
capybara
debug
devise (~> 4.9)
error_highlight (>= 0.4.0)
factory_bot_rails
faker
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ To execute the tests, run the following command inside the project folder (root)
- [x] Views.
- [x] Forms.
- [x] Integration specs for Views and fixing n+1 problems.
- [ ] Add Devise.
- [x] Add Devise.
- [ ] Add authorization rules.
- [ ] Add API endpoints.
- [ ] API documentation.
Expand Down
23 changes: 19 additions & 4 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
class ApplicationController < ActionController::Base
def current_user
# @current_user ||= User.find_by(id: session[:user_id])
# ! fetch first user for testing purposes. Remove this line when login system in place.
@current_user = User.first
before_action :authenticate_user!

protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :update_allowed_parameters, if: :devise_controller?

protected

def update_allowed_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:name, :bio, :email, :password) }
devise_parameter_sanitizer.permit(:account_update) do |u|
u.permit(:name, :email, :bio, :password, :current_password)
end
end

def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_in) do |user_params|
user_params.permit(:username, :email)
end
end
end
16 changes: 16 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable

before_create :set_default_photo

has_many :posts, class_name: 'Post', foreign_key: :author_id
has_many :comments, class_name: 'Comment', foreign_key: :user_id
has_many :likes, class_name: 'Like', foreign_key: :user_id
Expand All @@ -9,4 +16,13 @@ class User < ApplicationRecord
def most_recent_posts(n_limit = 3)
posts.includes(:likes, :comments).order(created_at: :desc).limit(n_limit)
end

private

def set_default_photo
photo_number = rand(1..5) # ? the below url can only handle 5 different photos.
photo_url = "https://robohash.org/accusantiumeaquea.png?size=200x200&set=set#{photo_number}"

self.photo ||= photo_url
end
end
26 changes: 26 additions & 0 deletions app/views/devise/confirmations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<main class="container mt-4" style="max-width: 900px; height: 80vh;">
<h2 class="text-muted text-center mb-4">Resend confirmation instructions &#128220;</h2>
<div style="max-width: 400px; margin: 0 auto;" class="mb-3">
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name),
html: { method: :post },
class: "form-control h-auto") do |f| %>

<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.email_field :email, autofocus: true, autocomplete: "email",
placeholder: "Email",
class: "form-control mb-2",
value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>

<div class="actions">
<%= f.submit "Resend confirmation instructions",
class: "btn btn-info px-2 py-1 w-100" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
</div>
</main>

5 changes: 5 additions & 0 deletions app/views/devise/mailer/confirmation_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<p>Welcome <%= @email %>!</p>

<p>You can confirm your account email through the link below:</p>

<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
7 changes: 7 additions & 0 deletions app/views/devise/mailer/email_changed.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p>Hello <%= @email %>!</p>

<% if @resource.try(:unconfirmed_email?) %>
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>
3 changes: 3 additions & 0 deletions app/views/devise/mailer/password_change.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p>Hello <%= @resource.email %>!</p>

<p>We're contacting you to notify you that your password has been changed.</p>
8 changes: 8 additions & 0 deletions app/views/devise/mailer/reset_password_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<p>Hello <%= @resource.email %>!</p>

<p>Someone has requested a link to change your password. You can do this through the link below.</p>

<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>

<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
7 changes: 7 additions & 0 deletions app/views/devise/mailer/unlock_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<p>Hello <%= @resource.email %>!</p>

<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>

<p>Click the link below to unlock your account:</p>

<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
25 changes: 25 additions & 0 deletions app/views/devise/passwords/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<h2>Change your password</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :reset_password_token %>

<div class="field">
<%= f.label :password, "New password" %><br />
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em><br />
<% end %>
<%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="actions">
<%= f.submit "Change my password" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
25 changes: 25 additions & 0 deletions app/views/devise/passwords/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<main class="container mt-4" style="max-width: 900px; height: 80vh;">
<h2 class="text-muted text-center mb-4">Forgot your password?</h2>
<div style="max-width: 400px; margin: 0 auto;" class="mb-3">
<%= form_for(resource, as: resource_name, url: password_path(resource_name),
html: { method: :post },
class: "form-control h-auto") do |f| %>

<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.email_field :email, autofocus: true,
autocomplete: "email",
placeholder: "Email",
class: "form-control mb-2" %>
</div>

<div class="actions">
<%= f.submit "Send me reset password instructions",
class: "btn btn-info px-2 py-1 w-100" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
</div>
</main>
43 changes: 43 additions & 0 deletions app/views/devise/registrations/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>

<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>

<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>

<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>

<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>

<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>

<h3>Cancel my account</h3>

<div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>

<%= link_to "Back", :back %>
43 changes: 43 additions & 0 deletions app/views/devise/registrations/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<main class="container mt-4" style="max-width: 900px; height: 80vh;">
<h2 class="text-muted text-center mb-4">Sign up! &#128513;</h2>
<div style="max-width: 400px; margin: 0 auto;" class="mb-3">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), class: "form-control h-auto") do |f| %>

<%= render "devise/shared/error_messages", resource: resource %>

<div class="field">
<%= f.text_field :name, autofocus: true,
autocomplete: "name",
placeholder: "Name",
class: "form-control mb-2" %>
</div>

<div class="field">
<%= f.email_field :email, autofocus: true,
autocomplete: "email",
placeholder: "Email",
class: "form-control mb-2" %>
</div>

<div class="field">
<%= f.password_field :password,
autocomplete: "new-password",
placeholder: "Password #{@minimum_password_length} characters minimum",
class: "form-control mb-2" %>
</div>

<div class="field">
<%= f.password_field :password_confirmation,
autocomplete: "new-password",
placeholder: "Confirm password",
class: "form-control mb-2" %>
</div>

<div class="actions">
<%= f.submit "Sign up", class: "btn btn-warning w-100" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
</div>
</main>
36 changes: 36 additions & 0 deletions app/views/devise/sessions/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<main class="container mt-4" style="max-width: 900px; height: 80vh;">
<h2 class="text-muted text-center mb-4">Log in</h2>
<div style="max-width: 400px; margin: 0 auto;" class="mb-3">
<%= form_for(resource, as: resource_name, url: session_path(resource_name),
class: "form-control h-auto") do |f| %>

<div class="field">
<%= f.email_field :email, autofocus: true,
autocomplete: "email",
placeholder: "Email",
class: "form-control mb-2" %>
</div>

<div class="field">
<%= f.password_field :password,
autocomplete: "current-password",
placeholder: "Password",
class: "form-control mb-2" %>
</div>

<% if devise_mapping.rememberable? %>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>

<div class="actions">
<%= f.submit "Log in", class: "btn btn-success w-100" %>
</div>
<% end %>

<%= render "devise/shared/links", button_type: "btn-outline-warning" %>
</div>
</main>

15 changes: 15 additions & 0 deletions app/views/devise/shared/_error_messages.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<% if resource.errors.any? %>
<div id="error_explanation" data-turbo-cache="false">
<h2>
<%= I18n.t("errors.messages.not_saved",
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
%>
</h2>
<ul>
<% resource.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
Loading
Loading