Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -40,6 +40,8 @@ group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: %i[mri mingw x64_mingw]
gem 'factory_bot_rails'
gem 'letter_opener'
gem 'letter_opener_web'
gem 'rubocop'
end

Expand Down
11 changes: 11 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ GEM
activerecord
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
launchy (2.5.2)
addressable (~> 2.8)
letter_opener (1.8.1)
launchy (>= 2.2, < 3)
letter_opener_web (2.0.0)
actionmailer (>= 5.2)
letter_opener (~> 1.7)
railties (>= 5.2)
rexml
listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
Expand Down Expand Up @@ -289,6 +298,8 @@ DEPENDENCIES
jbuilder (~> 2.7)
js-routes
kaminari
letter_opener
letter_opener_web
listen (~> 3.2)
pg (>= 0.18, < 2.0)
puma (~> 4.1)
Expand Down
7 changes: 3 additions & 4 deletions app/controllers/api/v1/tasks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@ def index
def create
params['task']['author_id'] = current_user.id if params.dig('task', 'author_id').nil?
task = current_user.my_tasks.new(task_params)
task.save

UserMailer.with({ user: current_user, task: task }).task_created.deliver_now if task.save
respond_with(task, serializer: TaskSerializer, location: nil)
end

def update
task = Task.find(params[:id])
task.update(task_params)
UserMailer.with({ task: task }).task_updated.deliver_now if task.update(task_params)

respond_with(task, serializer: TaskSerializer)
end

def destroy
task = Task.find(params[:id])
task.destroy
UserMailer.with({ task: task }).task_deleted.deliver_now if task.destroy

respond_with(task)
end
Expand Down
38 changes: 38 additions & 0 deletions app/controllers/web/password_resets_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class Web::PasswordResetsController < Web::ApplicationController
def new; end

def create
@user = User.find_by(email: params.dig('user', 'email'))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лучше через стронг параметры


if @user.present?
@token = @user.generate_token
UserMailer.with(user: @user, token: @token).reset_password.deliver_now
@user.update(reset_password_token_digest: @token)
end
redirect_to new_session_path
end

def edit
@user = GlobalID::Locator.locate_signed(params[:token], for: 'password_reset')
if @user.nil?
redirect_to new_session_path
elsif @user.reset_password_token_digest != params[:token]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для валидации данных, поступающих в контроллер, используют формы

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • пользователю необходимо сообщить что у него не так

redirect_to new_session_path
end
end

def update
@user = GlobalID::Locator.locate_signed(params[:token], for: 'password_reset')
if @user.update(password_params.merge(reset_password_token_digest: nil))
redirect_to new_session_path
else
render :edit
end
end

private

def password_params
params.require(:user).permit(:password, :password_confirmation)
end
end
29 changes: 29 additions & 0 deletions app/mailers/user_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class UserMailer < ApplicationMailer
def task_created
user = params[:user]
@task = params[:task]

mail(from: 'noreply@taskmanager.com', to: user.email, subject: 'New Task Created')
end

def task_updated
@task = params[:task]
author = @task.author

mail(from: 'noreply@taskmanager.com', to: author.email, subject: 'Task Updated')
end

def task_deleted
@task = params[:task]
author = @task.author

mail(from: 'noreply@taskmanager.com', to: author.email, subject: 'Task Deleted')
end

def reset_password
@user = params[:user]
@token = params[:token]

mail(from: 'noreply@taskmanager.com', to: @user.email, subject: 'Password Reset')
end
end
4 changes: 4 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ class User < ApplicationRecord
validates :first_name, presence: true, length: { minimum: 2 }
validates :last_name, presence: true, length: { minimum: 2 }
validates :email, presence: true, uniqueness: true, format: { with: /\w*@{1}\w*/ }

def generate_token
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

метод не относится к модели. Нужно вынести в отдельный сервис

to_sgid(for: 'password_reset', expires_in: 1.day).to_s
end
end
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ html lang="en"
footer#footer.mdl-mini-footer
.mdl-mini-footer__left-section
.mdl-logo
| &copy; Dualboot Learn 2020
| &copy; Dualboot Learn 2023
3 changes: 3 additions & 0 deletions app/views/layouts/mailer.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
html
body
= yield
1 change: 1 addition & 0 deletions app/views/layouts/mailer.text.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
= yield
6 changes: 6 additions & 0 deletions app/views/user_mailer/_body.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
tr
td bgcolor="#ffffff" style="padding: 10px 30px;"
p
| Dear user!
p
| We are honored to announce you that Task #{@task.id} was #{action}.
5 changes: 5 additions & 0 deletions app/views/user_mailer/_footer.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tr
td
small
center style="color: #d3d3d3;"
| &copy; Dualboot Learn 2023
5 changes: 5 additions & 0 deletions app/views/user_mailer/_header.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
tr
td bgcolor="#3F52B5" align="center" style="padding: 30px 0;"
span style="color:#ffffff; font-size: 20px; font-family:Arial, Helvetica, sans-serif;"
b
Task Board Project
19 changes: 19 additions & 0 deletions app/views/user_mailer/reset_password.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
doctype html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
html lang="en"
head
meta http-equiv="Content-Type" content="text/html; charset=utf-8"
title="Email template"
body bgcolor="#efefef" style="padding: 0; margin: 0"
table border="0" cellpadding="0" cellspacing="0" width="100%"
tr
td align="center"
table width="600" border="0" cellpadding="30" cellspacing="0"
==render 'header'
tr
td bgcolor="#ffffff" style="padding: 10px 30px;"
p
| Dear user!
p
= link_to 'Click this link, to reset your password', edit_password_resets_url(token: @token)
==render 'footer'
14 changes: 14 additions & 0 deletions app/views/user_mailer/task_created.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
doctype html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
html lang="en"
head
meta http-equiv="Content-Type" content="text/html; charset=utf-8"
title="Email template"
body bgcolor="#efefef" style="padding: 0; margin: 0"
table border="0" cellpadding="0" cellspacing="0" width="100%"
tr
td align="center"
table width="600" border="0" cellpadding="30" cellspacing="0"
==render 'header'
==render 'body', object: @task, action: 'created'
==render 'footer'
14 changes: 14 additions & 0 deletions app/views/user_mailer/task_deleted.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
doctype html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
html lang="en"
head
meta http-equiv="Content-Type" content="text/html; charset=utf-8"
title="Email template"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

кажется еще есть общие участки кода

body bgcolor="#efefef" style="padding: 0; margin: 0"
table border="0" cellpadding="0" cellspacing="0" width="100%"
tr
td align="center"
table width="600" border="0" cellpadding="30" cellspacing="0"
==render 'header'
==render 'body', object: @task, action: 'deleted'
==render 'footer'
14 changes: 14 additions & 0 deletions app/views/user_mailer/task_updated.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
doctype html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
html lang="en"
head
meta http-equiv="Content-Type" content="text/html; charset=utf-8"
title="Email template"
body bgcolor="#efefef" style="padding: 0; margin: 0"
table border="0" cellpadding="0" cellspacing="0" width="100%"
tr
td align="center"
table width="600" border="0" cellpadding="30" cellspacing="0"
==render 'header'
==render 'body', object: @task, action: 'updated'
==render 'footer'
7 changes: 7 additions & 0 deletions app/views/web/password_resets/edit.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
h4 Reset your password
= simple_form_for :user, url: password_resets_path(token: params[:token]), method: :put do |f|
p
= f.input :password
= f.input :password_confirmation
p
= f.button :submit, "Change pass"
7 changes: 7 additions & 0 deletions app/views/web/password_resets/new.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
h4 Forgot password? No problem!
p Type your email here, we'll send you link.
= simple_form_for :user, url: password_resets_path do |f|
p
= f.input :email
p
= f.button :submit, "Send"
1 change: 1 addition & 0 deletions app/views/web/sessions/new.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ h4 Log in
= f.input :password
p
= f.button :submit, "Sign in"
= link_to "Forgot Password?", new_password_resets_path, class: 'mdl-navigation__link'
4 changes: 3 additions & 1 deletion config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false

config.action_mailer.perform_caching = false
config.action_mailer.delivery_method = :letter_opener_web
config.action_mailer.perform_caching = true
config.action_mailer.default_url_options = { host: 'localhost:3330' }

# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
Expand Down
10 changes: 10 additions & 0 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@
# config.active_job.queue_name_prefix = "app_production"

config.action_mailer.perform_caching = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
user_name: ENV['MAILER_USERNAME'],
password: ENV['MAILER_PASSWORD'],
address: ENV['MAILER_ADDRESS'],
port: ENV['MAILER_PORT'],
domain: ENV['MAILER_DOMAIN'],
authentication: ENV['MAILER_AUTHENTICATION'],
enable_starttls_auto: true
}

# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
Expand Down
1 change: 1 addition & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
config.active_storage.service = :test

config.action_mailer.perform_caching = false
config.action_mailer.default_url_options = { host: 'localhost:3330' }

# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
Expand Down
3 changes: 2 additions & 1 deletion config/initializers/simple_form_materialize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
config.boolean_style = :inline
config.item_wrapper_tag = :p

config.wrappers :materialize_form, tag: 'div', class: 'mdl-textfield mdl-js-textfield mdl-textfield--floating-label', error_class: 'is-invalid' do |b|
config.wrappers :materialize_form, tag: 'div', class: 'mdl-textfield mdl-js-textfield mdl-textfield--floating-label',
error_class: 'is-invalid' do |b|
b.use :html5
b.use :placeholder
b.optional :maxlength
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Rails.application.routes.draw do
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?
root to: 'web/boards#show'

scope module: :web do
resource :board, only: :show
resource :session, only: %i[new create destroy]
resources :developers, only: %i[new create]
resource :password_resets, only: %i[new create edit update]
end

namespace :admin do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddResetPasswordTokenToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :reset_password_token_digest, :string
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2020_10_04_112023) do
ActiveRecord::Schema.define(version: 2023_01_05_072548) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand All @@ -35,6 +35,7 @@
t.string "type"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "reset_password_token_digest"
end

end
13 changes: 11 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ version: '3.7'
services:
web:
build: .
volumes: &web-volumes
volumes:
&web-volumes
- &app-volume .:/task_manager:cached
- ~/.ssh:/root/.ssh
- ~/.bash_history:/root/.bash_history
Expand All @@ -14,7 +15,8 @@ services:
- 3332:3332
depends_on:
- db
environment: &web-environment
environment:
&web-environment
BUNDLE_PATH: /bundle_cache
GEM_HOME: /bundle_cache
GEM_PATH: /bundle_cache
Expand All @@ -23,6 +25,13 @@ services:
DATABASE_HOST: db
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: postgres

MAILER_USERNAME: fake
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не очень решение. Пересобирать контейнер при добавлении/удалении переменных не очень хочется

MAILER_PASSWORD: fake
MAILER_ADDRESS: fake
MAILER_PORT: fake
MAILER_DOMAIN: fake
MAILER_AUTHENTICATION: fake
command: bundle exec rails s -b '0.0.0.0' -p 3330

db:
Expand Down
Loading