ahoy_email 2.0.1 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
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