Skip to content

Commit

Permalink
Enabling SMTP feature to send emails via ActionMailer (#584)
Browse files Browse the repository at this point in the history
* Enabling SMTP feature to send emails via ActionMailer

* fixing rubocop offenses - TrailingEmptyLines

* Linting Issues on .Vue files

* SMTP controller logic modified to welcome project,component users; Created Instance Variables to Avoid DB Model access from views

* Removed project reference as this is related to a component

* reduced db round trips

---------

Co-authored-by: Sai Pavan Marlakunta <smarlakunta@vmware.com>
  • Loading branch information
smarlaku820 and Sai Pavan Marlakunta authored May 29, 2023
1 parent cdf09a8 commit ac486ee
Show file tree
Hide file tree
Showing 13 changed files with 319 additions and 3 deletions.
9 changes: 9 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ def slack_notification_params(notification_type, object)
}
end

def send_smtp_notification(mailer, action, *args)
mailer.request_review(*args).deliver_now if action == 'request_review'
mailer.approve_review(*args).deliver_now if action == 'approve'
mailer.revoke_review(*args).deliver_now if action == 'revoke_review_request'
mailer.request_review_changes(*args).deliver_now if action == 'request_changes'
mailer.welcome_project_member(*args).deliver_now if action == 'project_user'
mailer.welcome_component_member(*args).deliver_now if action == 'component_user'
end

private

def helpful_errors(exception)
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/memberships_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ def create
flash.notice = 'Successfully created membership.'
case membership.membership_type
when 'Project'
send_smtp_notification(UserMailer, 'project_user', current_user, membership) if Settings.smtp.enabled
send_membership_notification(:create_project_membership, membership)
when 'Component'
send_smtp_notification(UserMailer, 'component_user', current_user, membership) if Settings.smtp.enabled
send_membership_notification(:create_component_membership, membership)
end
redirect_to membership.membership
Expand Down
15 changes: 13 additions & 2 deletions app/controllers/reviews_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@ class ReviewsController < ApplicationController
before_action :authorize_author_project

def create
review = Review.new(review_params.merge({ user: current_user, rule: @rule }))
review_params_without_component_id = review_params.except('component_id')
review = Review.new(review_params_without_component_id.merge({ user: current_user, rule: @rule }))
if review.save
if Settings.smtp.enabled
send_smtp_notification(
UserMailer,
review_params[:action],
current_user,
review_params[:component_id],
review_params[:comment],
@rule
)
end
render json: { toast: 'Successfully added review.' }
else
render json: {
Expand Down Expand Up @@ -81,6 +92,6 @@ def set_project
end

def review_params
params.require(:review).permit(:action, :comment)
params.require(:review).permit(:component_id, :action, :comment)
end
end
2 changes: 1 addition & 1 deletion app/javascript/components/rules/RuleEditorHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@
required
/>
</b-form-group>

<!-- Review action -->
<b-form-group label="" class="mb-0">
<b-form-radio
Expand Down Expand Up @@ -469,6 +468,7 @@ export default {
axios
.post(`/rules/${this.rule.id}/reviews`, {
review: {
component_id: this.rule.component_id,
action: this.selectedReviewAction,
comment: this.reviewComment.trim(),
},
Expand Down
128 changes: 128 additions & 0 deletions app/mailers/user_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# frozen_string_literal: true

# Sends Email Notifications to users if Vulcan is configured to use an SMTP server
class UserMailer < ApplicationMailer
def welcome_project_member(*args)
parse_mailer_welcome_user_args(*args)
begin
mail(
to: @user.email,
cc: @project_admins,
subject: "Vulcan Project Access - #{@project.name}",
from: Settings.smtp.settings.user_name
)
rescue StandardError => e
Rails.logger.error("Error delivering welcome email to user #{@user.name}: #{e.message}")
end
end

def welcome_component_member(*args)
parse_mailer_welcome_user_args(*args)
begin
mail(
to: @user.email,
cc: @project_admins,
subject: "Vulcan Component Access - #{@component.name}",
from: Settings.smtp.settings.user_name
)
rescue StandardError => e
Rails.logger.error("Error delivering welcome email to user #{@user.name}: #{e.message}")
end
end

def request_review(*args)
parse_mailer_review_args(*args)
begin
mail(
to: @project_admins,
cc: @current_user.email,
subject: "Review Requested - #{@stig_id}",
from: Settings.smtp.settings.user_name
)
rescue StandardError => e
Rails.logger.error("Error delivering request_review by user #{@current_user.name}: #{e.message}")
end
end

def approve_review(*args)
parse_mailer_review_args(*args)
@latest_review_user = find_latest_request_review(@rule, @component_id)
begin
mail(
to: @latest_review_user.email,
cc: @project_admins,
subject: "Review Approved - #{@stig_id}",
from: Settings.smtp.settings.user_name
)
rescue StandardError => e
Rails.logger.error("Error delivering approve_review by user #{@current_user.name}: #{e.message}")
end
end

def revoke_review(*args)
parse_mailer_review_args(*args)
@latest_review_user = find_latest_request_review(@rule, @component_id)
begin
mail(
to: @latest_review_user.email,
cc: @project_admins,
subject: "Review Revoked - #{@stig_id}",
from: Settings.smtp.settings.user_name
)
rescue StandardError => e
Rails.logger.error("Error delivering revoke_review_request by user #{@current_user.name}: #{e.message}")
end
end

def request_review_changes(*args)
parse_mailer_review_args(*args)
@latest_review_user = find_latest_request_review(@rule, @component_id)
begin
mail(
to: @latest_review_user.email,
cc: @project_admins,
subject: "Requesting Changes on the Review - #{@stig_id}",
from: Settings.smtp.settings.user_name
)
rescue StandardError => e
Rails.logger.error("Error delivering request_review_changes by user #{@current_user.name}: #{e.message}")
end
end

private

def get_project_admins(project_id)
Project.find(project_id).users.where(memberships: { role: 'admin' }).pluck(:email)
end

def parse_mailer_review_args(*args)
@current_user, @component_id, @comment, @rule = args
@stig_id = "#{Component.find(@component_id).prefix}-#{@rule.rule_id}"
@project_id = Component.find(@component_id).project.id
@project_admins = get_project_admins(@project_id)
end

def parse_mailer_welcome_user_args(*args)
@current_user, @membership = args
case @membership.membership_type
when 'Project'
@project_id = @membership.membership_id
@project = Project.find(@project_id)
when 'Component'
@component_id = @membership.membership_id
@component = Component.find(@component_id)
@project_id = @component.project_id
end
@project_admins = get_project_admins(@project_id)
@user = User.find(@membership.user_id)
@role_assigned = @membership.role.to_s
end

def find_latest_request_review(rule, component_id)
latest_review = Review.where(
rule_id: Rule.find_by(rule_id: rule.rule_id.to_s, component_id: component_id).id,
action: 'request_review'
).order(updated_at: :desc).first
latest_review.user
end
end
44 changes: 44 additions & 0 deletions app/views/user_mailer/_shared_styles.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
<style>
body {
font-family: Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
color: #333;
background-color: #f8f8f8;
padding: 20px;
}

h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 10px;
font-family: Arial, sans-serif;
font-weight: bold;
color: #333;
}

p, blockquote {
margin-top: 0;
margin-bottom: 10px;
font-family: Arial, sans-serif;
color: #333;
}

a {
color: #007bff;
text-decoration: none;
}

a:hover {
color: #0056b3;
text-decoration: underline;
}

blockquote {
border-left: 5px solid #007bff;
padding-left: 10px;
}
</style>
</head>

21 changes: 21 additions & 0 deletions app/views/user_mailer/approve_review.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<%= render 'user_mailer/shared_styles' %>
<body>
<h2>Hi <%=@latest_review_user.name %>,</h2>
<% if Settings.app_url.present? %>
<p><%= @current_user.name %> approved review on <%= link_to @stig_id, "#{Settings.app_url}/components/#{@component_id}/#{@stig_id}" %> .</p>
<% else %>
<p><%= @current_user.name %> approved review on <%= @stig_id %>.</p>
<% end %>
<h3>The approved comments are:</h3>
<blockquote>
<%= @comment %>
</blockquote>
<br/>
<br/>
<p>Thank you,</p>
<p>Vulcan Support</p>
</body>
</html>

21 changes: 21 additions & 0 deletions app/views/user_mailer/request_review.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<%= render 'user_mailer/shared_styles' %>
<body>
<h2>Hello ProjectAdmins,</h2>
<% if Settings.app_url.present? %>
<p><%= @current_user.name %> requested review on <%= link_to @stig_id, "#{Settings.app_url}/components/#{@component_id}/#{@stig_id}" %> .</p>
<% else %>
<p><%= @current_user.name %> requested review on <%= @stig_id %>.</p>
<% end %>
<h3>The review comment is:</h3>
<blockquote>
<%= @comment %>
</blockquote>
<br/>
<br/>
<p>Thank you,</p>
<p>Vulcan Support</p>
</body>
</html>

21 changes: 21 additions & 0 deletions app/views/user_mailer/request_review_changes.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<%= render 'user_mailer/shared_styles' %>
<body>
<h2>Hi <%=@latest_review_user.name %>,</h2>
<% if Settings.app_url.present? %>
<p><%= @current_user.name %> requested changes on the review <%= link_to @stig_id, "#{Settings.app_url}/components/#{@component_id}/#{@stig_id}" %> .</p>
<% else %>
<p><%= @current_user.name %> requested changes on the review <%= @stig_id %>.</p>
<% end %>
<h3>The comments are:</h3>
<blockquote>
<%= @comment %>
</blockquote>
<br/>
<br/>
<p>Thank you,</p>
<p>Vulcan Support</p>
</body>
</html>

21 changes: 21 additions & 0 deletions app/views/user_mailer/revoke_review.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<%= render 'user_mailer/shared_styles' %>
<body>
<h2>Hi <%=@latest_review_user.name %>,</h2>
<% if Settings.app_url.present? %>
<p><%= @current_user.name %> revoked review on <%= link_to @stig_id, "#{Settings.app_url}/components/#{@component_id}/#{@stig_id}" %> .</p>
<% else %>
<p><%= @current_user.name %> revoked review on <%= @stig_id %>.</p>
<% end %>
<h3>The revoked comments are:</h3>
<blockquote>
<%= @comment %>
</blockquote>
<br/>
<br/>
<p>Thank you,</p>
<p>Vulcan Support</p>
</body>
</html>

18 changes: 18 additions & 0 deletions app/views/user_mailer/welcome_component_member.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<%= render 'user_mailer/shared_styles' %>
<body>
<h2>Vulcan Component Access</h2>
<p>Hi <%= @user.name %>,</p>
<p>You have been added to the <%= @role_assigned %> role in the <%= @component.name %> component.</p>
<% if Settings.app_url.present? %>
<p>You can access the component at <%= link_to @component.name, "#{Settings.app_url}/components/#{@component_id}" %> .</p>
<% else %>
<p>You can access the component "<%= @component.name %>".</p>
<% end %>
<br/>
<br/>
<p>Thank you,</p>
<p>Vulcan Support</p>
</body>
</html>
18 changes: 18 additions & 0 deletions app/views/user_mailer/welcome_project_member.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<%= render 'user_mailer/shared_styles' %>
<body>
<h2>Vulcan Project Access</h2>
<p>Hi <%= @user.name %>,</p>
<p>You have been added to the <%= @role_assigned %> role in the <%= @project.name %> project.</p>
<% if Settings.app_url.present? %>
<p>You can access the project at <%= link_to @project.name, "#{Settings.app_url}/projects/#{@project_id}" %> .</p>
<% else %>
<p>You can access the project "<%= @project.name %>".</p>
<% end %>
<br/>
<br/>
<p>Thank you,</p>
<p>Vulcan Support</p>
</body>
</html>
2 changes: 2 additions & 0 deletions config/initializers/smtp_settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

if Rails.env.production? && Settings.smtp.enabled
Rails.application.config.action_mailer.delivery_method = :smtp
Rails.application.config.action_mailer.perform_deliveries = true
Rails.application.config.action_mailer.raise_delivery_errors = true

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = Settings.smtp.settings.transform_keys(&:to_sym)
Expand Down

0 comments on commit ac486ee

Please sign in to comment.