Merge branch 'master' into 177717903-move-constants-to-configuration-file

This commit is contained in:
Jimmy 2021-04-13 12:06:59 +08:00
commit e08a465889
15 changed files with 319 additions and 2 deletions

View file

@ -57,6 +57,8 @@ class ConferenceRegistrationsController < ApplicationController
sign_in(@registration.user)
end
MailblusterEditLeadJob.perform_later(@user, add_tags: ["snapcon-#{@conference.short_title}"])
if @conference.tickets.visible.any? && !current_user.supports?(@conference)
redirect_to conference_tickets_path(@conference.short_title),
notice: 'You are now registered and will be receiving E-Mail notifications.'
@ -87,6 +89,7 @@ class ConferenceRegistrationsController < ApplicationController
def destroy
if @registration.destroy
MailblusterEditLeadJob.perform_later(@user, remove_tags: ["snapcon-#{@conference.short_title}"])
redirect_to root_path,
notice: "You are not registered for #{@conference.title} anymore!"
else

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class MailblusterCreateLeadJob < ApplicationJob
queue_as :default
def perform(user)
MailblusterManager.create_lead(user)
end
end

View file

@ -0,0 +1,7 @@
class MailblusterDeleteLeadJob < ApplicationJob
queue_as :default
def perform(user)
MailblusterManager.delete_lead(user)
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
class MailblusterEditLeadJob < ApplicationJob
queue_as :default
def perform(user, add_tags: [], remove_tags: [], old_email: nil)
MailblusterManager.edit_lead(user, add_tags: add_tags, remove_tags: remove_tags, old_email: old_email)
end
end

View file

@ -0,0 +1,48 @@
# https://github.com/ccmcbeck/after-commit
module TrackSavedChanges
extend ActiveSupport::Concern
included do
# expose the details if consumer wants to do more
# attr_reader :ts_saved_changes_history, :ts_saved_changes_unfiltered
after_initialize :ts_reset_saved_changes
after_save :ts_track_saved_changes
end
# on initalize, but useful for fine grain control
def ts_reset_saved_changes
@ts_saved_changes_unfiltered = {}
@ts_saved_changes_history = []
end
# filter out any changes that result in the original value
def ts_saved_changes
@ts_saved_changes_unfiltered.reject { |_k, v| v[0] == v[1] }
end
private
# on save
def ts_track_saved_changes
# maintain an array of ActiveModel::Dirty.changes
@ts_saved_changes_history << previous_changes.dup
# accumulate the most recent changes
@ts_saved_changes_history.last.each_pair { |k, v| ts_track_saved_change k, v }
end
# v is an an array of [prev, current]
def ts_track_saved_change(key, value)
if @ts_saved_changes_unfiltered.key? key
@ts_saved_changes_unfiltered[key][1] = ts_track_saved_value value[1]
else
@ts_saved_changes_unfiltered[key] = value.dup
end
end
# type safe dup inspred by http://stackoverflow.com/a/20955038
def ts_track_saved_value(value)
value.dup
rescue TypeError
value
end
end

View file

@ -195,6 +195,7 @@ class Program < ApplicationRecord
# * +True+ -> If there is any event for the given date
# * +False+ -> If there is not any event for the given date
def any_event_for_this_date?(date)
return false if date.nil? || date == ''
return false unless selected_schedule.present?
parsed_date = DateTime.parse("#{date} 00:00").utc

View file

@ -53,6 +53,7 @@ class UserDisabled < StandardError
end
class User < ApplicationRecord
include TrackSavedChanges
rolify
# prevent N+1 queries with has_cached_role? by preloading roles *always*
default_scope { preload(:roles) }
@ -80,6 +81,12 @@ class User < ApplicationRecord
after_save :touch_events
# Note that using after_create_commit and after_update_commit does not work.
# See https://github.com/CactusPuppy/snapcon/pull/43#discussion_r609458034
after_commit :mailbluster_create_lead, on: :create
after_commit :mailbluster_delete_lead, on: :destroy
after_commit :mailbluster_update_lead, on: :update, if: ->(user){ ['name', 'email'].any? { |key| user.ts_saved_changes.key? key } }
# add scope
scope :comment_notifiable, ->(conference) {joins(:roles).where('roles.name IN (?)', [:organizer, :cfp]).where('roles.resource_type = ? AND roles.resource_id = ?', 'Conference', conference.id)}
@ -361,12 +368,32 @@ class User < ApplicationRecord
User.count == 1 && User.first.email == 'deleted@localhost.osem'
end
# TODO: email_hash function for mailbluster
# def email_hash
# Digest::MD5.hexdigest user.email
# end
private
def setup_role
self.is_admin = true if User.empty?
end
def mailbluster_create_lead
MailblusterCreateLeadJob.perform_later self
ts_reset_saved_changes
end
def mailbluster_delete_lead
MailblusterDeleteLeadJob.perform_later email
ts_reset_saved_changes
end
def mailbluster_update_lead
MailblusterEditLeadJob.perform_later(self, old_email: ts_saved_changes.fetch('email', [nil])[0])
ts_reset_saved_changes
end
def touch_events
event_users.each(&:touch)
end

View file

@ -0,0 +1,40 @@
class MailblusterManager
include HTTParty
base_uri 'https://api.mailbluster.com/api/leads/'
@auth_headers = {
headers: {
'Content-Type' => 'application/json',
'Authorization' => ENV['MAILBLUSTER_API_KEY']
}
}
def self.query_api(method, path, body: {})
options = @auth_headers.merge(body: body.to_json)
send(method, path, options).parsed_response
end
def self.create_lead(user)
query_api(:post, '/', body: {
'email' => user.email,
'firstName' => user.name,
'overrideExisting' => true,
'subscribed' => true,
'tags' => [ENV['OSEM_NAME'] || 'snapcon']
})
end
def self.edit_lead(user, add_tags: [], remove_tags: [], old_email: nil)
email_hash = Digest::MD5.hexdigest(old_email.presence || user.email)
query_api(:put, "/#{email_hash}", body: {
'email' => user.email,
'firstName' => user.name,
'addTags' => add_tags,
'removeTags' => remove_tags
})
end
def self.delete_lead(email)
email_hash = Digest::MD5.hexdigest email
query_api(:delete, "/#{email_hash}")
end
end

View file

@ -2,4 +2,4 @@ $('#happening-now').html("<%= j(render 'happening_now', conference: @conference,
events_schedules: @events_schedules, pagy: @pagy,
events_schedules_length: @events_schedules_length,
events_schedules_limit: @events_schedules_limit)%>");
Pagy.init(document.getElementById('happening-now'));
Pagy.init(document.getElementById('happening-now'));