ahoy_email 2.0.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69eb9c77891a37c75ef7f7683211c90159cbb8aefd64fa14a0b1b35d2e16d0eb
4
- data.tar.gz: a937ba8e9362d1c2551f5c193b9a3bbf1b4132f3df9ddb77f3f838f633fb2f07
3
+ metadata.gz: bf88f44f04ee798926e9363928aed4be7c34d0b4f5456b01f1dc210f18967cc4
4
+ data.tar.gz: bb0c2ea92f067cbd6f37f7d06bb7700f51427dd68f178d0405ccf31f02b21fea
5
5
  SHA512:
6
- metadata.gz: 4b12c970be432d7db95fdb8eaade5766f69fc7826a94f41474ba5c2a35da1ea85b6317f83250cb1c8f41c7fe876028b1377958709d2c84ff9bd303926ac8ab5a
7
- data.tar.gz: 96dcc647ee3777e27b14d7628025d96ea92efce7160d36da0b066b72d9dc5aac8196008699a93673d81d0fdcb909aa69874b349dffdbaf0e32e4d7511a32df5a
6
+ metadata.gz: 9568577466f777d12ad274926490b72f0976eec913b12e8e524f3af66612f22a9a07fa5065c5e2f8817b735ee4ed683a2391b62211aadda716168b3b12833f4b
7
+ data.tar.gz: 122f4e7758d69d4cba1c16b3ff677317084b562921db52d7bcd9408b760aa5ef3e5ebd61808e04e39c1f6e538722d51247daba68037bad88939338049db6f80e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 2.1.1 (2021-12-13)
2
+
3
+ - Added experimental support for Active Record encryption
4
+
5
+ ## 2.1.0 (2021-09-25)
6
+
7
+ - Fixed mailer `default_url_options` not being applied to click links
8
+
9
+ ## 2.0.3 (2021-03-31)
10
+
11
+ - Fixed `utm_params` and `track_clicks` stripping `<head>` tags from messages
12
+
13
+ ## 2.0.2 (2021-03-14)
14
+
15
+ - Added support for Mongoid to database subscriber
16
+
1
17
  ## 2.0.1 (2021-03-08)
2
18
 
3
19
  - Added database subscriber
data/README.md CHANGED
@@ -28,17 +28,24 @@ There are three main features, which can be used independently:
28
28
 
29
29
  ## Message History
30
30
 
31
- To encrypt email addresses, install [Lockbox](https://github.com/ankane/lockbox) and [Blind Index](https://github.com/ankane/blind_index) and run:
31
+ To encrypt email addresses with Lockbox, install [Lockbox](https://github.com/ankane/lockbox) and [Blind Index](https://github.com/ankane/blind_index) and run:
32
32
 
33
33
  ```sh
34
- rails generate ahoy:messages
34
+ rails generate ahoy:messages --encryption=lockbox
35
+ rails db:migrate
36
+ ```
37
+
38
+ To use Active Record encryption (Rails 7+, experimental), run:
39
+
40
+ ```sh
41
+ rails generate ahoy:messages --encryption=activerecord
35
42
  rails db:migrate
36
43
  ```
37
44
 
38
45
  If you prefer not to encrypt data, run:
39
46
 
40
47
  ```sh
41
- rails generate ahoy:messages --unencrypted
48
+ rails generate ahoy:messages --encryption=none
42
49
  rails db:migrate
43
50
  ```
44
51
 
@@ -157,7 +164,7 @@ Ahoy::Message.where("created_at < ?", 1.year.ago).in_batches.delete_all
157
164
  Delete data for a specific user with:
158
165
 
159
166
  ```ruby
160
- Ahoy::Message.where(user_id: 1).in_batches.delete_all
167
+ Ahoy::Message.where(user_id: 1, user_type: "User").in_batches.delete_all
161
168
  ```
162
169
 
163
170
  ## UTM Tagging
@@ -285,6 +292,14 @@ class CouponMailer < ApplicationMailer
285
292
  end
286
293
  ```
287
294
 
295
+ You can also use a proc
296
+
297
+ ```ruby
298
+ class CouponMailer < ApplicationMailer
299
+ track_clicks campaign: -> { "coupon-#{action_name}" }
300
+ end
301
+ ```
302
+
288
303
  Skip specific links with:
289
304
 
290
305
  ```erb
@@ -10,9 +10,16 @@ module AhoyEmail
10
10
 
11
11
  def stats(campaign)
12
12
  sends = Ahoy::Message.where(campaign: campaign).count
13
- result = Ahoy::Click.where(campaign: campaign).select("COUNT(*) AS clicks, COUNT(DISTINCT token) AS unique_clicks").to_a[0]
14
- clicks = result.clicks
15
- unique_clicks = result.unique_clicks
13
+
14
+ if defined?(ActiveRecord) && Ahoy::Click < ActiveRecord::Base
15
+ result = Ahoy::Click.where(campaign: campaign).select("COUNT(*) AS clicks, COUNT(DISTINCT token) AS unique_clicks").to_a[0]
16
+ clicks = result.clicks
17
+ unique_clicks = result.unique_clicks
18
+ else
19
+ clicks = Ahoy::Click.where(campaign: campaign).count
20
+ # TODO use aggregation framework
21
+ unique_clicks = Ahoy::Click.where(campaign: campaign).distinct(:token).count
22
+ end
16
23
 
17
24
  if sends > 0 || clicks > 0
18
25
  {
@@ -25,7 +32,11 @@ module AhoyEmail
25
32
  end
26
33
 
27
34
  def campaigns
28
- Ahoy::Message.where.not(campaign: nil).distinct.pluck(:campaign)
35
+ if defined?(ActiveRecord) && Ahoy::Message < ActiveRecord::Base
36
+ Ahoy::Message.where.not(campaign: nil).distinct.pluck(:campaign)
37
+ else
38
+ Ahoy::Message.where(campaign: {"$ne" => nil}).distinct(:campaign)
39
+ end
29
40
  end
30
41
  end
31
42
  end
@@ -53,7 +53,7 @@ module AhoyEmail
53
53
  if html_part?
54
54
  part = message.html_part || message
55
55
 
56
- doc = Nokogiri::HTML::DocumentFragment.parse(part.body.raw_source)
56
+ doc = Nokogiri::HTML::Document.parse(part.body.raw_source)
57
57
  doc.css("a[href]").each do |link|
58
58
  uri = parse_uri(link["href"])
59
59
  next unless trackable?(uri)
@@ -123,7 +123,7 @@ module AhoyEmail
123
123
  end
124
124
 
125
125
  def url_for(opt)
126
- opt = (ActionMailer::Base.default_url_options || {})
126
+ opt = (mailer.default_url_options || {})
127
127
  .merge(options[:url_options])
128
128
  .merge(opt)
129
129
  AhoyEmail::Engine.routes.url_helpers.url_for(opt)
@@ -1,3 +1,3 @@
1
1
  module AhoyEmail
2
- VERSION = "2.0.1"
2
+ VERSION = "2.1.1"
3
3
  end
@@ -0,0 +1,15 @@
1
+ require "rails/generators"
2
+
3
+ module Ahoy
4
+ module Generators
5
+ module Clicks
6
+ class MongoidGenerator < Rails::Generators::Base
7
+ source_root File.join(__dir__, "templates")
8
+
9
+ def copy_templates
10
+ template "mongoid.rb", "app/models/ahoy/click.rb"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ class Ahoy::Click
2
+ include Mongoid::Document
3
+
4
+ field :campaign, type: String
5
+ field :token, type: String
6
+
7
+ index({campaign: 1})
8
+ end
@@ -4,7 +4,33 @@ module Ahoy
4
4
  module Generators
5
5
  class ClicksGenerator < Rails::Generators::Base
6
6
  def copy_templates
7
- invoke "ahoy:clicks:activerecord"
7
+ activerecord = defined?(ActiveRecord)
8
+ mongoid = defined?(Mongoid)
9
+
10
+ selection =
11
+ if activerecord && mongoid
12
+ puts <<-MSG
13
+
14
+ Which data store would you like to use?
15
+ 1. Active Record (default)
16
+ 2. Mongoid
17
+ MSG
18
+
19
+ ask(">")
20
+ elsif activerecord
21
+ "1"
22
+ else
23
+ "2"
24
+ end
25
+
26
+ case selection
27
+ when "", "1"
28
+ invoke "ahoy:clicks:activerecord"
29
+ when "2"
30
+ invoke "ahoy:clicks:mongoid"
31
+ else
32
+ abort "Error: must enter a number [1-2]"
33
+ end
8
34
  end
9
35
  end
10
36
  end
@@ -7,15 +7,21 @@ module Ahoy
7
7
  include ActiveRecord::Generators::Migration
8
8
  source_root File.join(__dir__, "templates")
9
9
 
10
+ class_option :encryption, type: :string
11
+ # deprecated
10
12
  class_option :unencrypted, type: :boolean
11
13
 
12
14
  def copy_migration
15
+ encryption # ensure valid
13
16
  migration_template "migration.rb", "db/migrate/create_ahoy_messages.rb", migration_version: migration_version
14
17
  end
15
18
 
16
19
  def copy_template
17
- if encrypted?
18
- template "model_encrypted.rb", "app/models/ahoy/message.rb"
20
+ case encryption
21
+ when "lockbox"
22
+ template "model_lockbox.rb", "app/models/ahoy/message.rb"
23
+ when "activerecord"
24
+ template "model_activerecord.rb", "app/models/ahoy/message.rb"
19
25
  end
20
26
  end
21
27
 
@@ -24,15 +30,30 @@ module Ahoy
24
30
  end
25
31
 
26
32
  def to_column
27
- if encrypted?
33
+ case encryption
34
+ when "lockbox"
28
35
  "t.text :to_ciphertext\n t.string :to_bidx, index: true"
29
36
  else
37
+ # TODO add limit: 510 for Active Record encryption + MySQL?
30
38
  "t.string :to, index: true"
31
39
  end
32
40
  end
33
41
 
34
- def encrypted?
35
- !options[:unencrypted]
42
+ # TODO remove default
43
+ def encryption
44
+ case options[:encryption]
45
+ when "lockbox", "activerecord", "none"
46
+ options[:encryption]
47
+ when nil
48
+ if options[:unencrypted]
49
+ # TODO deprecation warning
50
+ "none"
51
+ else
52
+ "lockbox"
53
+ end
54
+ else
55
+ abort "Error: encryption must be lockbox, activerecord, or none"
56
+ end
36
57
  end
37
58
  end
38
59
  end
@@ -6,13 +6,33 @@ module Ahoy
6
6
  class MongoidGenerator < Rails::Generators::Base
7
7
  source_root File.join(__dir__, "templates")
8
8
 
9
+ class_option :encryption, type: :string
10
+ # deprecated
9
11
  class_option :unencrypted, type: :boolean
10
12
 
11
13
  def copy_templates
12
- if options[:unencrypted]
14
+ case encryption
15
+ when "lockbox"
16
+ template "mongoid_lockbox.rb", "app/models/ahoy/message.rb"
17
+ else
13
18
  template "mongoid.rb", "app/models/ahoy/message.rb"
19
+ end
20
+ end
21
+
22
+ # TODO remove default
23
+ def encryption
24
+ case options[:encryption]
25
+ when "lockbox", "none"
26
+ options[:encryption]
27
+ when nil
28
+ if options[:unencrypted]
29
+ # TODO deprecation warning
30
+ "none"
31
+ else
32
+ "lockbox"
33
+ end
14
34
  else
15
- template "mongoid_encrypted.rb", "app/models/ahoy/message.rb"
35
+ abort "Error: encryption must be lockbox or none"
16
36
  end
17
37
  end
18
38
  end
@@ -0,0 +1,7 @@
1
+ class Ahoy::Message < ActiveRecord::Base
2
+ self.table_name = "ahoy_messages"
3
+
4
+ belongs_to :user, polymorphic: true, optional: true
5
+
6
+ encrypts :to, deterministic: true
7
+ end
@@ -3,6 +3,8 @@ require "rails/generators"
3
3
  module Ahoy
4
4
  module Generators
5
5
  class MessagesGenerator < Rails::Generators::Base
6
+ class_option :encryption, type: :string
7
+ # deprecated
6
8
  class_option :unencrypted, type: :boolean
7
9
 
8
10
  def copy_templates
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahoy_email
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-08 00:00:00.000000000 Z
11
+ date: 2021-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -92,14 +92,17 @@ files:
92
92
  - lib/ahoy_email/utils.rb
93
93
  - lib/ahoy_email/version.rb
94
94
  - lib/generators/ahoy/clicks/activerecord_generator.rb
95
+ - lib/generators/ahoy/clicks/mongoid_generator.rb
95
96
  - lib/generators/ahoy/clicks/templates/migration.rb.tt
97
+ - lib/generators/ahoy/clicks/templates/mongoid.rb.tt
96
98
  - lib/generators/ahoy/clicks_generator.rb
97
99
  - lib/generators/ahoy/messages/activerecord_generator.rb
98
100
  - lib/generators/ahoy/messages/mongoid_generator.rb
99
101
  - lib/generators/ahoy/messages/templates/migration.rb.tt
100
- - lib/generators/ahoy/messages/templates/model_encrypted.rb.tt
102
+ - lib/generators/ahoy/messages/templates/model_activerecord.rb.tt
103
+ - lib/generators/ahoy/messages/templates/model_lockbox.rb.tt
101
104
  - lib/generators/ahoy/messages/templates/mongoid.rb.tt
102
- - lib/generators/ahoy/messages/templates/mongoid_encrypted.rb.tt
105
+ - lib/generators/ahoy/messages/templates/mongoid_lockbox.rb.tt
103
106
  - lib/generators/ahoy/messages_generator.rb
104
107
  homepage: https://github.com/ankane/ahoy_email
105
108
  licenses:
@@ -120,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
123
  - !ruby/object:Gem::Version
121
124
  version: '0'
122
125
  requirements: []
123
- rubygems_version: 3.2.3
126
+ rubygems_version: 3.2.32
124
127
  signing_key:
125
128
  specification_version: 4
126
129
  summary: First-party email analytics for Rails