diff --git a/Gemfile b/Gemfile
index b6814db..7bbf738 100644
--- a/Gemfile
+++ b/Gemfile
@@ -76,3 +76,5 @@ group :test do
gem 'selenium-webdriver'
gem 'webdrivers'
end
+
+gem 'devise', '~> 4.9'
diff --git a/Gemfile.lock b/Gemfile.lock
index 7a74f3d..9e6af4b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -69,6 +69,7 @@ GEM
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
+ bcrypt (3.1.19)
bindex (0.8.1)
bootsnap (1.16.0)
msgpack (~> 1.2)
@@ -88,6 +89,12 @@ GEM
debug (1.7.1)
irb (>= 1.5.0)
reline (>= 0.3.1)
+ devise (4.9.2)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0)
+ responders
+ warden (~> 1.2.3)
diff-lcs (1.5.0)
erubi (1.12.0)
globalid (1.1.0)
@@ -130,6 +137,7 @@ GEM
nio4r (2.5.9)
nokogiri (1.15.2-x64-mingw-ucrt)
racc (~> 1.4)
+ orm_adapter (0.5.0)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
@@ -174,6 +182,9 @@ GEM
regexp_parser (2.8.1)
reline (0.3.5)
io-console (~> 0.5)
+ responders (3.1.0)
+ actionpack (>= 5.2)
+ railties (>= 5.2)
rexml (3.2.5)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
@@ -230,6 +241,8 @@ GEM
tzinfo-data (1.2023.3)
tzinfo (>= 1.0.0)
unicode-display_width (2.4.2)
+ warden (1.2.9)
+ rack (>= 2.0.9)
web-console (4.2.0)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
@@ -254,6 +267,7 @@ DEPENDENCIES
bootsnap
capybara
debug
+ devise (~> 4.9)
importmap-rails
jbuilder
pg (~> 1.1)
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index b46953e..f2bd3aa 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -53,6 +53,7 @@
a {
text-decoration: none;
+ color: black;
}
.user-bio {
@@ -148,6 +149,134 @@ button {
border-radius: 5px;
}
+/* style the authentification pages */
+.auth_pages {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1rem;
+ color: black;
+ font-size: large;
+ width: 50vw;
+ margin: 100px auto;
+ padding: 1rem;
+ background-color: #c4ddae;
+ border: 1px solid gray;
+}
+
+form {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ width: 40vw;
+ margin: auto auto;
+}
+
+form input {
+ width: 30vw;
+ padding: 0.5rem;
+}
+
+.shared {
+ display: flex;
+ flex-direction: column-reverse;
+ gap: 0;
+ width: 30vw;
+ padding-bottom: 0.5rem;
+}
+
+.shared a {
+ color: black !important;
+}
+
+ul {
+ list-style: none;
+}
+
+.actions {
+ border: 1px solid #1e1d1d;
+ border-radius: 5px;
+ box-shadow: 1px 1px 1px 1px #1e1d1d;
+}
+
+.actions input {
+ cursor: pointer;
+ font-size: 16.5px;
+}
+
+.remember_me {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: stretch;
+ gap: 0.5rem;
+}
+
+.remember_me input {
+ width: 1rem;
+ height: 1rem;
+}
+
+.auth_links {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 1rem;
+ width: 30vw;
+ margin: auto auto;
+}
+
+.auth_links a {
+ color: blue;
+ padding: 0.5rem;
+ box-shadow: #1e1d1d 1px 1px 1px 1px;
+}
+
+#error_explanation {
+ color: red;
+ font-size: large;
+}
+
+#error_explanation h2 {
+ font-size: large;
+ font-weight: normal;
+}
+
+.cancel_back {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ width: 50vw;
+}
+
+.cancel_account {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ gap: 1rem;
+}
+
+.cancel_back a {
+ color: rgb(104, 4, 235);
+ font-weight: bold;
+}
+
+.cancel_account .button_to {
+ width: 20vw;
+}
+
+.button_to button,
+.button_to button a {
+ cursor: pointer;
+ padding: 5px;
+ font-size: 15px;
+ color: blue;
+ border: none;
+}
+
.form-elements {
display: flex;
flex-direction: row;
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1d8dbda..227312a 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,5 +1,12 @@
class ApplicationController < ActionController::Base
- def current_user
- @current_user ||= User.first
+ before_action :authenticate_user!
+ before_action :configure_permitted_parameters, if: :devise_controller?
+
+ protected
+
+ def configure_permitted_parameters
+ devise_parameter_sanitizer.permit(:sign_up, keys: %i[name email password password_confirmation])
+ devise_parameter_sanitizer.permit(:account_update,
+ keys: %i[name email password password_confirmation current_password])
end
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 54c7d1c..c3c197c 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -7,6 +7,5 @@ def show
@user = User.find_by_id(params[:id])
redirect_to users_path if @user.nil?
- @posts = @user.posts
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index ccab1ee..9605970 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,8 @@
class User < ApplicationRecord
+ # Include default devise modules. Others available are:
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
+ devise :database_authenticatable, :registerable,
+ :recoverable, :rememberable, :validatable
has_many :posts, foreign_key: :author_id, dependent: :destroy
has_many :comments, foreign_key: :user_id, dependent: :destroy
has_many :likes, foreign_key: :user_id, dependent: :destroy
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb
new file mode 100644
index 0000000..4312792
--- /dev/null
+++ b/app/views/devise/confirmations/new.html.erb
@@ -0,0 +1,21 @@
+
+
+
Resend confirmation instructions
+
+ <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
+
+
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
+
+
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+ <%= f.submit "Resend confirmation instructions" %>
+
+ <% end %>
+
+ <%= render "devise/shared/links" %>
+
+
diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb
new file mode 100644
index 0000000..dc55f64
--- /dev/null
+++ b/app/views/devise/mailer/confirmation_instructions.html.erb
@@ -0,0 +1,5 @@
+Welcome <%= @email %>!
+
+You can confirm your account email through the link below:
+
+<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/email_changed.html.erb b/app/views/devise/mailer/email_changed.html.erb
new file mode 100644
index 0000000..32f4ba8
--- /dev/null
+++ b/app/views/devise/mailer/email_changed.html.erb
@@ -0,0 +1,7 @@
+Hello <%= @email %>!
+
+<% if @resource.try(:unconfirmed_email?) %>
+ We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.
+<% else %>
+ We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
+<% end %>
diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb
new file mode 100644
index 0000000..b41daf4
--- /dev/null
+++ b/app/views/devise/mailer/password_change.html.erb
@@ -0,0 +1,3 @@
+Hello <%= @resource.email %>!
+
+We're contacting you to notify you that your password has been changed.
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb
new file mode 100644
index 0000000..f667dc1
--- /dev/null
+++ b/app/views/devise/mailer/reset_password_instructions.html.erb
@@ -0,0 +1,8 @@
+Hello <%= @resource.email %>!
+
+Someone has requested a link to change your password. You can do this through the link below.
+
+<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
+
+If you didn't request this, please ignore this email.
+Your password won't change until you access the link above and create a new one.
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb
new file mode 100644
index 0000000..41e148b
--- /dev/null
+++ b/app/views/devise/mailer/unlock_instructions.html.erb
@@ -0,0 +1,7 @@
+Hello <%= @resource.email %>!
+
+Your account has been locked due to an excessive number of unsuccessful sign in attempts.
+
+Click the link below to unlock your account:
+
+<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb
new file mode 100644
index 0000000..2e695f6
--- /dev/null
+++ b/app/views/devise/passwords/edit.html.erb
@@ -0,0 +1,30 @@
+
+
+
Change your password
+
+ <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
+ <%= f.hidden_field :reset_password_token %>
+
+
+ <%= f.label :password, "New password" %>
+ <% if @minimum_password_length %>
+ (<%= @minimum_password_length %> characters minimum)
+ <% end %>
+ <%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
+
+
+
+ <%= f.label :password_confirmation, "Confirm new password" %>
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
+
+
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+ <%= f.submit "Change my password" %>
+
+ <% end %>
+
+ <%= render "devise/shared/links" %>
+
+
\ No newline at end of file
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
new file mode 100644
index 0000000..10142aa
--- /dev/null
+++ b/app/views/devise/passwords/new.html.erb
@@ -0,0 +1,20 @@
+
+
+
Forgot your password?
+
+ <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
+
+
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+ <%= f.submit "Send me reset password instructions" %>
+
+ <% end %>
+
+ <%= render "devise/shared/links" %>
+
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
new file mode 100644
index 0000000..fba58b7
--- /dev/null
+++ b/app/views/devise/registrations/edit.html.erb
@@ -0,0 +1,50 @@
+
+
+
Edit <%= resource_name.to_s.humanize %>
+
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
+
+
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+ <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
+
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
+ <% end %>
+
+
+ <%= f.label :password %> (leave blank if you don't want to change it)
+ <%= f.password_field :password, autocomplete: "new-password" %>
+ <% if @minimum_password_length %>
+
+ <%= @minimum_password_length %> characters minimum
+ <% end %>
+
+
+
+ <%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
+
+
+
+ <%= f.label :current_password %> (we need your current password to confirm your changes)
+ <%= f.password_field :current_password, autocomplete: "current-password" %>
+
+
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+ <%= f.submit "Update" %>
+
+ <% end %>
+
+
+
Unhappy?
+ <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %>
+
+
+ <%= link_to "Back", :back %>
+
+
+
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
new file mode 100644
index 0000000..ac81ff3
--- /dev/null
+++ b/app/views/devise/registrations/new.html.erb
@@ -0,0 +1,39 @@
+
+
+
Sign up
+
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
+
+
+ <%= f.label :name %>
+ <%= f.text_field :name, autofocus: true, placeholder: "Name" %>
+
+
+
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+ <%= f.label :password %>
+ <% if @minimum_password_length %>
+ (<%= @minimum_password_length %> characters minimum)
+ <% end %>
+ <%= f.password_field :password, autocomplete: "new-password" %>
+
+
+
+ <%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
+
+
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+ <%= f.submit "Sign up" %>
+
+ <% end %>
+
+ <%= render "devise/shared/links" %>
+
+
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
new file mode 100644
index 0000000..2cedc02
--- /dev/null
+++ b/app/views/devise/sessions/new.html.erb
@@ -0,0 +1,32 @@
+
+
Log in
+
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
+
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+ <%= f.label :password %>
+ <%= f.password_field :password, autocomplete: "current-password" %>
+
+
+ <% if devise_mapping.rememberable? %>
+
+ <%= f.check_box :remember_me %>
+ <%= f.label :remember_me %>
+
+ <% end %>
+
+ <% if alert %>
+
<%= alert %>
+ <% end %>
+
+
+ <%= f.submit "Log in" %>
+
+ <% end %>
+
+ <%= render "devise/shared/links" %>
+
diff --git a/app/views/devise/shared/_error_messages.html.erb b/app/views/devise/shared/_error_messages.html.erb
new file mode 100644
index 0000000..cabfe30
--- /dev/null
+++ b/app/views/devise/shared/_error_messages.html.erb
@@ -0,0 +1,15 @@
+<% if resource.errors.any? %>
+
+
+ <%= I18n.t("errors.messages.not_saved",
+ count: resource.errors.count,
+ resource: resource.class.model_name.human.downcase)
+ %>
+
+
+ <% resource.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+<% end %>
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb
new file mode 100644
index 0000000..d7f9526
--- /dev/null
+++ b/app/views/devise/shared/_links.html.erb
@@ -0,0 +1,28 @@
+
+ <%- if controller_name != 'sessions' %>
+ <%= link_to "Log in", new_session_path(resource_name) %>
+ <% end %>
+
+ <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
+ <%= link_to "Sign up", new_registration_path(resource_name) %>
+ <% end %>
+
+ <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
+ <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+ <% end %>
+
+ <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+ <% end %>
+
+ <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
+ <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+ <% end %>
+
+ <%- if devise_mapping.omniauthable? %>
+ <%- resource_class.omniauth_providers.each do |provider| %>
+ <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %>
+ <% end %>
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb
new file mode 100644
index 0000000..ffc34de
--- /dev/null
+++ b/app/views/devise/unlocks/new.html.erb
@@ -0,0 +1,16 @@
+Resend unlock instructions
+
+<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
+ <%= render "devise/shared/error_messages", resource: resource %>
+
+
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
+
+
+
+ <%= f.submit "Resend unlock instructions" %>
+
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 8b5b099..5fd34af 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,7 +1,7 @@
- RailsBlogApp
+ Rails Blog App
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
@@ -11,6 +11,19 @@
+
+ <% if user_signed_in? %>
+ Logged in as <%= current_user.name %>.
+ <%= link_to "Edit profile", edit_user_registration_path, class: "navbar-link" %> |
+ <%= link_to "Logout", destroy_user_session_path, data: { "turbo-method": :delete }, class: "navbar-link" %>
+ <% end %>
+
+ <% if notice %>
+ <%= notice %>
+ <% end %>
+
+
<%= yield %>
+
-
+