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

Slack notify integration #605

Open
wants to merge 12 commits into
base: v3.1
Choose a base branch
from
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ spec/dummy/public/uploads/*

/vendor
docker-compose.override.yml
.env
.env
mysql
node_modules
43 changes: 22 additions & 21 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ GIT
PATH
remote: .
specs:
fae-rails (3.0.0)
fae-rails (3.1.0)
acts_as_list (~> 0.9.11)
browser (~> 2.5.3)
carrierwave
devise (~> 4.0)
devise
devise-two-factor
jquery-rails (~> 4.3.1)
jquery-ui-rails (~> 6.0.1)
Expand All @@ -36,6 +36,7 @@ PATH
sass (>= 3.4.0)
sass-rails (>= 5.0.7)
simple_form (<= 5.1)
slack-notifier
slim
uglifier

Expand Down Expand Up @@ -148,13 +149,12 @@ GEM
capybara-screenshot (1.0.26)
capybara (>= 1.0, < 4)
launchy
carrierwave (2.2.2)
activemodel (>= 5.0.0)
activesupport (>= 5.0.0)
carrierwave (3.0.7)
activemodel (>= 6.0.0)
activesupport (>= 6.0.0)
addressable (~> 2.6)
image_processing (~> 1.1)
marcel (~> 1.0.0)
mini_mime (>= 0.1.3)
ssrf_filter (~> 1.0)
childprocess (4.1.0)
chunky_png (1.4.0)
Expand All @@ -175,7 +175,7 @@ GEM
msgpack
debase-ruby_core_source (0.10.16)
debug_inspector (1.1.0)
devise (4.9.3)
devise (4.9.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
Expand All @@ -191,7 +191,7 @@ GEM
erubi (1.12.0)
eventmachine (1.2.7)
excon (0.92.4)
execjs (2.8.1)
execjs (2.9.1)
factory_bot (4.8.2)
activesupport (>= 3.0.0)
factory_bot_rails (4.8.2)
Expand Down Expand Up @@ -283,7 +283,7 @@ GEM
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
mini_magick (4.11.0)
mini_magick (4.12.0)
mini_mime (1.1.2)
minitest (5.21.2)
msgpack (1.5.6)
Expand Down Expand Up @@ -371,8 +371,8 @@ GEM
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.5)
rotp (6.2.0)
rqrcode (2.1.2)
rotp (6.3.0)
rqrcode (2.2.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
Expand All @@ -398,7 +398,7 @@ GEM
rspec-support (~> 3.10)
rspec-support (3.11.0)
ruby-prof (1.4.3)
ruby-vips (2.1.4)
ruby-vips (2.2.1)
ffi (~> 1.12)
rubyzip (2.3.2)
sass (3.7.4)
Expand Down Expand Up @@ -426,28 +426,29 @@ GEM
simple_form (5.1.0)
actionpack (>= 5.2)
activemodel (>= 5.2)
slim (4.1.0)
temple (>= 0.7.6, < 0.9)
tilt (>= 2.0.6, < 2.1)
sprockets (4.0.3)
slack-notifier (2.4.0)
slim (5.2.1)
temple (~> 0.10.0)
tilt (>= 2.1.0)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sshkit (1.21.2)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
ssrf_filter (1.0.7)
ssrf_filter (1.1.2)
strscan (3.0.1)
temple (0.8.2)
temple (0.10.3)
thin (1.8.1)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
thor (1.3.0)
tilt (2.0.10)
tilt (2.3.0)
timeout (0.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
Expand Down Expand Up @@ -487,7 +488,7 @@ DEPENDENCIES
guard-rspec
mysql2
pg
pry-nav
pry
puma (~> 5.0)
rails (~> 7.0.2)
rails-controller-testing
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ https://www.faecms.com/documentation
* [Form Field Label & Helper Text Manager](docs/features/form_manager.md)
* [Netlify Deploy Monitor](docs/features/netlify.md)
* [Multi-Factor Authentication via OTP](docs/features/mutli_factor_authentication.md)
* [Slack Notifications](docs/features/slack_notifications.md)


### Tutorials
Expand Down
36 changes: 36 additions & 0 deletions app/models/concerns/fae/base_model_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,31 @@ module BaseModelConcern
included do
include Fae::Trackable if Fae.track_changes
include Fae::Sortable
after_create :notify_initiation
before_save :notify_changes
end

def notify_changes
return unless notifiable_attributes.present?
notifiable_attributes.each do |field_name_symbol|
if self.send("#{field_name_symbol}_changed?") && self.send(field_name_symbol).present?
jasonfine marked this conversation as resolved.
Show resolved Hide resolved
format_and_send_slack(field_name_symbol)
end
end
end

def notify_initiation
return unless notifiable_attributes.present?
notifiable_attributes.each do |field_name_symbol|
if self.send(field_name_symbol).present?
format_and_send_slack(field_name_symbol)
end
end
end

def notifiable_attributes
# override this method in your model
# array of attributes to notify if changed
end

def fae_display_field
Expand Down Expand Up @@ -36,6 +61,17 @@ def fae_form_manager_model_id
self.id
end

def slack_message(field_name_symbol)
# override this method in your model
end

def format_and_send_slack(field_name_symbol)
message = slack_message(field_name_symbol)
if message.present?
Fae::SlackNotification.new().send_slack(message: message)
end
end

module ClassMethods
def for_fae_index
order(order_method)
Expand Down
17 changes: 17 additions & 0 deletions app/services/fae/slack_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'slack-notifier'

module Fae
class SlackNotification

def send_slack(webhook: Fae.slack_webhook_url, message: nil)
if webhook.is_a?(String)
webhook = webhook.split(',')
end
webhook.each do |wh|
notifier = Slack::Notifier.new wh
notifier.ping message
end if webhook.present?
end

end
end
48 changes: 48 additions & 0 deletions docs/features/slack_notifications.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Slack Notifications

Built around the `slack-notifier` gem, FAE now offers the ability to send a message to a Slack channel when an object is created or saved.

Add the Slack webhook URL(s) to your `fae.rb` file. It can be a single value, or comma separated for multiple:

```
# fae.rb
config.slack_webhook_url = ENV['SLACK_WEBHOOK_URL']
```

FAE's `base_model_concern.rb` has two new callbacks:

```ruby
after_create :notify_initiation
before_save :notify_changes
```

Models created with FAE's scaffold generators include this concern by default so you shouldn't need to take any action here.

However, there are a couple of new instance methods to drive this in your models:

```ruby
def notifiable_attributes
# array of attributes to notify if changed e.g.:
[:slug, :on_prod]
end
```


```ruby
def slack_message(field_name_symbol)
case field_name_symbol
when :on_prod
status = self.on_prod? ? 'live' : 'not live'
msg = ''
msg += "#{Rails.application.class.module_parent_name} - "
msg += "[#{name}](#{Rails.application.routes.url_helpers.edit_admin_wine_url(self)}) "
msg += "(#{self.class.name.constantize}) is #{status} "
msg += "#{field_name_symbol.to_s.gsub('_',' ')}"
return msg
when :slug
# Different message for slug changes.
end
end
```

As illustrated, you can customize the messages as you wish.
1 change: 1 addition & 0 deletions fae.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Gem::Specification.new do |s|
s.add_dependency 'slim'
s.add_dependency 'devise-two-factor'
s.add_dependency 'rqrcode'
s.add_dependency 'slack-notifier'

s.add_development_dependency 'appraisal'
s.add_development_dependency 'better_errors'
Expand Down
3 changes: 2 additions & 1 deletion lib/fae/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

module Fae
# configurable defaults
mattr_accessor :devise_secret_key, :devise_mailer_sender, :dashboard_exclusions, :max_image_upload_size, :max_file_upload_size, :languages, :recreate_versions, :validation_helpers, :track_changes, :tracker_history_length, :slug_separator, :disabled_environments, :per_page, :use_cache, :use_form_manager, :netlify
mattr_accessor :devise_secret_key, :devise_mailer_sender, :dashboard_exclusions, :max_image_upload_size, :max_file_upload_size, :languages, :recreate_versions, :validation_helpers, :track_changes, :tracker_history_length, :slug_separator, :disabled_environments, :per_page, :use_cache, :use_form_manager, :netlify, :slack_webhook_url

self.devise_secret_key = ''
self.devise_mailer_sender = '[email protected]'
Expand All @@ -22,6 +22,7 @@ module Fae
self.use_cache = false
self.use_form_manager = false
self.netlify = {}
self.slack_webhook_url = ''

# this function maps the vars from your app into your engine
def self.setup(&block)
Expand Down
4 changes: 4 additions & 0 deletions lib/generators/fae/templates/initializers/fae.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,8 @@
# site_id: 'site-id-in-netlify',
# api_base: 'https://api.netlify.com/api/v1/'
# }

## slack_webhook_url
# Environment variable is recommended for any sensitive Slack configuration details.
config.slack_webhook_url = ENV['SLACK_WEBHOOK_URL']
end
13 changes: 13 additions & 0 deletions spec/dummy/app/models/wine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,17 @@ def self.for_fae_index
order(:position)
end

def notifiable_attributes
[:on_stage, :on_prod, :description_en]
end

def slack_message(field_name_symbol)
msg = ''
msg += "#{Rails.application.class.module_parent_name} - "
msg += "[#{name}](#{Rails.application.routes.url_helpers.edit_admin_wine_url(self)}) "
msg += "(#{self.class.name.constantize}) is live "
msg += "#{field_name_symbol.to_s.gsub('_',' ')}"
msg
end

end
5 changes: 4 additions & 1 deletion spec/dummy/config/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@
# Initialize the Rails application.
Rails.application.initialize!

ActiveRecord::Migrator.migrations_paths = '../spec/dummy/db/migrate'
ActiveRecord::Migrator.migrations_paths = '../spec/dummy/db/migrate'

# Set the default host and port to be the same as Action Mailer.
Rails.application.default_url_options = Rails.application.config.action_mailer.default_url_options
2 changes: 2 additions & 0 deletions spec/dummy/config/initializers/fae.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@
api_base: 'https://api.netlify.com/api/v1/'
}
end

config.slack_webhook_url = ENV['SLACK_WEBHOOK_URL']
end
23 changes: 23 additions & 0 deletions spec/models/fae/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,27 @@
end
end

describe '#format_and_send_slack' do
it 'should send a slack notification if message is present' do
wine = FactoryBot.create(:wine)
field_name_symbol = :on_prod

test_message = "Dummy - [asdf](http://localhost/admin/wines/#{wine.id}/edit) (Wine) is live on prod"
allow(wine).to receive(:slack_message).with(field_name_symbol).and_return(test_message)
expect(Fae::SlackNotification).to receive(:new).and_return(double(send_slack: true))

wine.format_and_send_slack(field_name_symbol)
end

it 'should not send a slack notification if message is not present' do
wine = FactoryBot.create(:wine)
field_name_symbol = :name_en

allow(wine).to receive(:slack_message).with(field_name_symbol).and_return(nil)
expect(Fae::SlackNotification).not_to receive(:new)

wine.format_and_send_slack(field_name_symbol)
end
end

end