1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-11-28 09:24:24 +01:00

(quality) replacement of the gem NotifyWith by internal code

This commit is contained in:
Karen 2023-01-27 13:53:23 +01:00 committed by Sylvain
parent 10de4fcf5e
commit 54dbd5ef4d
23 changed files with 217 additions and 137 deletions

View File

@ -103,8 +103,6 @@ gem 'elasticsearch-persistence', '~> 5'
gem 'elasticsearch-rails', '~> 5'
gem 'faraday', '~> 0.17'
gem 'notify_with'
gem 'pundit'
gem 'oj'

View File

@ -236,10 +236,6 @@ GEM
nokogiri (1.13.10)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
notify_with (0.0.2)
jbuilder (~> 2.0)
rails (>= 4.2.0)
responders (~> 2.0)
oauth2 (1.4.4)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
@ -531,7 +527,6 @@ DEPENDENCIES
message_format
mini_magick
minitest-reporters
notify_with
oj
omniauth (~> 1.9.2)
omniauth-oauth2

View File

@ -3,8 +3,8 @@
# API Controller for resources of type Notification
# Notifications are scoped by user
class API::NotificationsController < API::ApiController
include NotifyWith::NotificationsApi
before_action :authenticate_user!
before_action :set_notification, only: :update
# notifications can have anything attached, so we won't eager load the whole database
around_action :skip_bullet, if: -> { defined?(Bullet) }
@ -14,7 +14,10 @@ class API::NotificationsController < API::ApiController
def index
loop do
@notifications = current_user.notifications.includes(:attached_object).page(params[:page]).per(NOTIFICATIONS_PER_PAGE).order('created_at DESC')
@notifications = current_user.notifications
.includes(:attached_object)
.page(params[:page])
.per(NOTIFICATIONS_PER_PAGE).order('created_at DESC')
# we delete obsolete notifications on first access
break unless delete_obsoletes(@notifications)
end
@ -27,7 +30,11 @@ class API::NotificationsController < API::ApiController
def last_unread
loop do
@notifications = current_user.notifications.includes(:attached_object).where(is_read: false).limit(3).order('created_at DESC')
@notifications = current_user.notifications
.includes(:attached_object)
.where(is_read: false)
.limit(3)
.order('created_at DESC')
# we delete obsolete notifications on first access
break unless delete_obsoletes(@notifications)
end
@ -49,8 +56,22 @@ class API::NotificationsController < API::ApiController
render :index
end
def update
@notification.mark_as_read
render :show
end
def update_all
current_user.notifications.where(is_read: false).find_each(&:mark_as_read)
head :no_content
end
private
def set_notification
@notification = current_user.notifications.find(params[:id])
end
def delete_obsoletes(notifications)
cleaned = false
notifications.each do |n|

View File

@ -1,11 +1,8 @@
# frozen_string_literal: true
# Handle most of the emails sent by the platform. Triggered by notifications
class NotificationsMailer < NotifyWith::NotificationsMailer
default from: ->(*) { Setting.get('email_from') }
layout 'notifications_mailer'
helper :application
class NotificationsMailer < BaseMailer
after_action :mark_notification_as_send
def send_mail_by(notification)
@notification = notification
@ -13,14 +10,14 @@ class NotificationsMailer < NotifyWith::NotificationsMailer
@attached_object = notification.attached_object
unless respond_to?(notification.notification_type)
class_eval %{
def #{notification.notification_type}
mail to: @recipient.email,
subject: t('notifications_mailer.#{notification.notification_type}.subject'),
template_name: '#{notification.notification_type}',
content_type: 'text/html'
end
}, __FILE__, __LINE__ - 7
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
def #{notification.notification_type} # def notify_admin_when_project_published
mail to: @recipient.email, # mail to: @recipient.email,
subject: t('notifications_mailer.#{notification.notification_type}.subject'), # subject: t('notifications_mailer.notify_admin_when_project_published.subject'),
template_name: '#{notification.notification_type}', # template_name: 'notify_admin_when_project_published',
content_type: 'text/html' # content_type: 'text/html'
end # end
RUBY
end
send(notification.notification_type)
@ -28,10 +25,6 @@ class NotificationsMailer < NotifyWith::NotificationsMailer
Rails.logger.error "[NotificationsMailer] notification cannot be sent: #{e}"
end
def helpers
ActionController::Base.helpers
end
def notify_user_when_invoice_ready
attachments[@attached_object.filename] = File.read(@attached_object.file)
mail(to: @recipient.email,
@ -59,4 +52,10 @@ class NotificationsMailer < NotifyWith::NotificationsMailer
subject: t('notifications_mailer.notify_member_create_reservation.subject'),
template_name: 'notify_member_create_reservation')
end
private
def mark_notification_as_send
@notification.mark_as_send unless @notification.is_send
end
end

View File

@ -3,7 +3,7 @@
# Abuse is a report made by a visitor (not especially a logged user) who has signaled a content that seems abusive to his eyes.
# It is currently used with projects.
class Abuse < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
belongs_to :signaled, polymorphic: true
@ -11,7 +11,6 @@ class Abuse < ApplicationRecord
validates :first_name, :last_name, :email, :message, presence: true
private
def notify_admins_abuse_reported

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
# Concern use to delete a notification if its attached object is detroyed
module NotificationAttachedObject
extend ActiveSupport::Concern
included do
after_destroy :clean_notification
def clean_notification
Notification.where('attached_object_id = :id and attached_object_type = :type', { id: id, type: self.class.to_s })
.destroy_all
end
end
end

View File

@ -2,7 +2,7 @@
# Event is an happening organized by the Fablab about a general topic, which does not involve Machines or trainings member's skills.
class Event < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
include ApplicationHelper
has_one :event_image, as: :viewable, dependent: :destroy

View File

@ -2,7 +2,7 @@
# Invoice correspond to a single purchase made by an user. This purchase is linked to one or many invoice_items
class Invoice < PaymentDocument
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
require 'fileutils'
scope :only_invoice, -> { where(type: nil) }

View File

@ -2,7 +2,36 @@
# Notification is an in-system alert that is shown to a specific user until it is marked as read.
class Notification < ApplicationRecord
include NotifyWith::Notification
belongs_to :notification_type
belongs_to :receiver, polymorphic: true
belongs_to :attached_object, polymorphic: true
validates :receiver_id,
:receiver_type,
:attached_object_id,
:attached_object_type,
:notification_type_id,
presence: true
def notification_type
NotificationType.find(notification_type_id).name
end
def mark_as_read
update(is_read: true)
end
def mark_as_send
update(is_send: true)
end
def deliver_now
NotificationsMailer.send_mail_by(self).deliver_now if save
end
def deliver_later
NotificationsMailer.send_mail_by(self).deliver_later if save
end
def get_meta_data(key)
meta_data.try(:[], key.to_s)

View File

@ -1,84 +1,7 @@
# frozen_string_literal: true
# NotificationType defines the different types of Notification.
class NotificationType
include NotifyWith::NotificationType
# DANGER: dont remove a notification type!!!
notification_type_names %w[
notify_admin_when_project_published
notify_project_collaborator_to_valid
notify_project_author_when_collaborator_valid
notify_user_training_valid
notify_member_subscribed_plan
notify_member_create_reservation
notify_member_subscribed_plan_is_changed
notify_admin_member_create_reservation
notify_member_slot_is_modified
notify_admin_slot_is_modified
notify_admin_when_user_is_created
notify_admin_subscribed_plan
notify_user_when_invoice_ready
notify_member_subscription_will_expire_in_7_days
notify_member_subscription_is_expired
notify_admin_subscription_will_expire_in_7_days
notify_admin_subscription_is_expired
notify_admin_subscription_canceled
notify_member_subscription_canceled
notify_user_when_avoir_ready
notify_member_slot_is_canceled
notify_admin_slot_is_canceled
notify_partner_subscribed_plan
notify_member_subscription_extended
notify_admin_subscription_extended
notify_admin_user_group_changed
notify_user_user_group_changed
notify_admin_when_user_is_imported
notify_user_profile_complete
notify_user_auth_migration
notify_admin_user_merged
notify_admin_profile_complete
notify_admin_abuse_reported
notify_admin_invoicing_changed
notify_user_wallet_is_credited
notify_admin_user_wallet_is_credited
notify_admin_export_complete
notify_member_about_coupon
notify_member_reservation_reminder
notify_admin_free_disk_space
notify_admin_close_period_reminder
notify_admin_archive_complete
notify_privacy_policy_changed
notify_admin_import_complete
notify_admin_refund_created
notify_admins_role_update
notify_user_role_update
notify_admin_objects_stripe_sync
notify_user_when_payment_schedule_ready
notify_admin_payment_schedule_failed
notify_member_payment_schedule_failed
notify_admin_payment_schedule_check_deadline
notify_admin_payment_schedule_transfer_deadline
notify_admin_payment_schedule_error
notify_member_payment_schedule_error
notify_admin_payment_schedule_gateway_canceled
notify_member_payment_schedule_gateway_canceled
notify_admin_user_proof_of_identity_files_created
notify_admin_user_proof_of_identity_files_updated
notify_user_is_validated
notify_user_is_invalidated
notify_user_proof_of_identity_refusal
notify_admin_user_proof_of_identity_refusal
notify_user_order_is_ready
notify_user_order_is_canceled
notify_user_order_is_refunded
notify_admin_low_stock_threshold
notify_admin_training_auto_cancelled
notify_member_training_auto_cancelled
notify_member_training_authorization_expired
notify_member_training_invalidated
]
# deprecated:
# - notify_member_subscribed_plan_is_changed
# - notify_admin_invoicing_changed
class NotificationType < ApplicationRecord
has_many :notifications, dependent: :destroy
validates :name, uniqueness: true, presence: true
end

View File

@ -2,7 +2,7 @@
# OfferDay provides a way for admins to extend the subscription of a member for free.
class OfferDay < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
has_many :invoice_items, as: :object, dependent: :destroy
belongs_to :subscription
@ -32,5 +32,4 @@ class OfferDay < ApplicationRecord
attached_object: subscription,
meta_data: meta_data
end
end

View File

@ -4,7 +4,7 @@
# It can describe the steps taken by the fab-user to build his object, provide photos, description, attached CAO files, etc.
class Project < ApplicationRecord
include AASM
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
include OpenlabSync
include PgSearch::Model

View File

@ -3,14 +3,14 @@
# ProjectUser is the relation table between a Project and an User.
# Users are collaborators to a Project, with write access if they have confirmed their participation.
class ProjectUser < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
belongs_to :project
belongs_to :user
before_create :generate_valid_token
after_commit :notify_project_collaborator_to_valid, on: :create
after_update :notify_project_author_when_collaborator_valid, if: :saved_change_to_is_valid?
after_commit :notify_project_collaborator_to_valid, on: :create
private

View File

@ -4,7 +4,7 @@
# Slots are for Machine, Space and Training reservations.
# Tickets are for Event reservations.
class Reservation < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
include ICalendarConcern
belongs_to :statistic_profile

View File

@ -4,7 +4,7 @@
# Slots duration are defined globally by Setting.get('slot_duration') but can be
# overridden per availability.
class Slot < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
has_many :slots_reservations, dependent: :destroy
has_many :reservations, through: :slots_reservations

View File

@ -2,7 +2,7 @@
# Stores trainings validated per user (non validated trainings are only recorded in reservations)
class StatisticProfileTraining < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
belongs_to :statistic_profile
belongs_to :training

View File

@ -2,7 +2,7 @@
# Subscription is an active or archived subscription of an User to a Plan
class Subscription < ApplicationRecord
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
belongs_to :plan
belongs_to :statistic_profile

View File

@ -3,9 +3,7 @@
# User is a physical or moral person with its authentication parameters
# It is linked to the Profile model with hold information about this person (like address, name, etc.)
class User < ApplicationRecord
include NotifyWith::NotificationReceiver
include NotifyWith::NotificationAttachedObject
include NotificationAttachedObject
include SingleSignOnConcern
include UserRoleConcern
include UserRessourcesConcern
@ -52,6 +50,8 @@ class User < ApplicationRecord
has_many :proof_of_identity_files, dependent: :destroy
has_many :proof_of_identity_refusals, dependent: :destroy
has_many :notifications, as: :receiver, dependent: :destroy
# fix for create admin user
before_save do
email&.downcase!

View File

@ -3,6 +3,7 @@
# track of all transactions payed using the given wallet
class WalletTransaction < ApplicationRecord
include AmountConcern
include NotificationAttachedObject
belongs_to :invoicing_profile
belongs_to :wallet

View File

@ -3,17 +3,14 @@
# send notification to one or several receiver with a type, an attached object and an optional meta data
class NotificationCenter
def self.call(type: nil, receiver: nil, attached_object: nil, meta_data: {})
if receiver.respond_to?(:each)
receiver.each do |user|
Notification.new(meta_data: meta_data)
.send_notification(type: type, attached_object: attached_object)
.to(user)
.deliver_later
end
else
Notification.new(meta_data: meta_data)
.send_notification(type: type, attached_object: attached_object)
.to(receiver)
receiver = [receiver] unless receiver.respond_to?(:each)
receiver.each do |user|
Notification.new(
meta_data: meta_data,
attached_object: attached_object,
receiver: user,
notification_type: NotificationType.find_by(name: type)
)
.deliver_later
end
end

View File

@ -1 +0,0 @@
NotifyWith.mailer = NotificationsMailer

View File

@ -0,0 +1,105 @@
# frozen_string_literal: true
# Creates Notification Types table to record every notification type (previously
# stored in an Array), and records the existing types.
# This migration is linked to the abandon of the NotifyWith gem. Notification Types
# will now be store in database and we will manage ourself the Notification system.
class CreateNotificationTypes < ActiveRecord::Migration[5.2]
NAMES = %w[
notify_admin_when_project_published
notify_project_collaborator_to_valid
notify_project_author_when_collaborator_valid
notify_user_training_valid
notify_member_subscribed_plan
notify_member_create_reservation
notify_member_subscribed_plan_is_changed
notify_admin_member_create_reservation
notify_member_slot_is_modified
notify_admin_slot_is_modified
notify_admin_when_user_is_created
notify_admin_subscribed_plan
notify_user_when_invoice_ready
notify_member_subscription_will_expire_in_7_days
notify_member_subscription_is_expired
notify_admin_subscription_will_expire_in_7_days
notify_admin_subscription_is_expired
notify_admin_subscription_canceled
notify_member_subscription_canceled
notify_user_when_avoir_ready
notify_member_slot_is_canceled
notify_admin_slot_is_canceled
notify_partner_subscribed_plan
notify_member_subscription_extended
notify_admin_subscription_extended
notify_admin_user_group_changed
notify_user_user_group_changed
notify_admin_when_user_is_imported
notify_user_profile_complete
notify_user_auth_migration
notify_admin_user_merged
notify_admin_profile_complete
notify_admin_abuse_reported
notify_admin_invoicing_changed
notify_user_wallet_is_credited
notify_admin_user_wallet_is_credited
notify_admin_export_complete
notify_member_about_coupon
notify_member_reservation_reminder
notify_admin_free_disk_space
notify_admin_close_period_reminder
notify_admin_archive_complete
notify_privacy_policy_changed
notify_admin_import_complete
notify_admin_refund_created
notify_admins_role_update
notify_user_role_update
notify_admin_objects_stripe_sync
notify_user_when_payment_schedule_ready
notify_admin_payment_schedule_failed
notify_member_payment_schedule_failed
notify_admin_payment_schedule_check_deadline
notify_admin_payment_schedule_transfer_deadline
notify_admin_payment_schedule_error
notify_member_payment_schedule_error
notify_admin_payment_schedule_gateway_canceled
notify_member_payment_schedule_gateway_canceled
notify_admin_user_proof_of_identity_files_created
notify_admin_user_proof_of_identity_files_updated
notify_user_is_validated
notify_user_is_invalidated
notify_user_proof_of_identity_refusal
notify_admin_user_proof_of_identity_refusal
notify_user_order_is_ready
notify_user_order_is_canceled
notify_user_order_is_refunded
notify_admin_low_stock_threshold
notify_admin_training_auto_cancelled
].freeze
def up
create_table :notification_types do |t|
t.string :name, null: false
t.timestamps
end
add_index :notification_types, :name, unique: true
# Records previous notification types
# Index start at 1. This is required due to previous functionning of the NotifyWith gem
NAMES.each.with_index(1) do |type, index|
NotificationType.create!(id: index, name: type)
end
last_id = NotificationType.order(:id).last.id
execute "SELECT setval('public.notification_types_id_seq', #{last_id})"
add_foreign_key :notifications, :notification_types
end
def down
remove_foreign_key :notifications, :notification_types
drop_table :notification_types
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2023_01_31_104958) do
ActiveRecord::Schema.define(version: 2023_01_26_160900) do
# These are extensions that must be enabled in order to support this database
enable_extension "fuzzystrmatch"