ahoy_email 2.1.0 → 2.1.3

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: b84f8c566d81a470ba99f4318c2d7dd3f1b3fae6b05155491f486cbdbff7c0a6
4
- data.tar.gz: 8ab62441cf6df6b4ab6af401a9cbed8864ac634d28dd728f6b83bfd743dce284
3
+ metadata.gz: b465af2a0497b6b85237fa5246c4c722d594978e07710f66ec96a9260fb44c98
4
+ data.tar.gz: 3f5e353adebbc67fbea887d9a8e36f01ba237a04d16431947855c81fc8be1bcd
5
5
  SHA512:
6
- metadata.gz: cf70b92f9ba7b0d91324eae1927fe49464c3b3a76293272570559526064d20a1df5a3859a350dac9d6708113b787e8566a8db58cb6bc881d463ae2f4581865c8
7
- data.tar.gz: 62019c44c7e66c5d3858c9862d20276dbb876d024ca21d1d8691e3969944778c493fa3e988e0e22e2253c7515a6d453d2f11c794867941fa024017c9f28eeb02
6
+ metadata.gz: ead0edcbeda702bd605ea00562addfb65cb321e6797a2fb0e8c1fed640511d8bb5bb2b34a4acfa3bde12447bb0401d0975548661bc867cc7e5c1b5585db01425
7
+ data.tar.gz: c903baeebe4fbd700a58d9e193094648ccf0a3205e70fd78fb20a84cf09dfaee3f642ef45d78e4a50eb86d287b9d0974e8d33075528eef03702fe311175aa5e1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 2.1.3 (2022-06-12)
2
+
3
+ - Updated messages generator for Lockbox 1.0
4
+ - Fixed deprecation warning with Redis 4.6+
5
+
6
+ ## 2.1.2 (2022-02-09)
7
+
8
+ - Fixed external redirects with Rails 7
9
+
10
+ ## 2.1.1 (2021-12-13)
11
+
12
+ - Added experimental support for Active Record encryption
13
+
1
14
  ## 2.1.0 (2021-09-25)
2
15
 
3
16
  - Fixed mailer `default_url_options` not being applied to click links
data/README.md CHANGED
@@ -15,7 +15,7 @@ First-party email analytics for Rails
15
15
  Add this line to your application’s Gemfile:
16
16
 
17
17
  ```ruby
18
- gem 'ahoy_email'
18
+ gem "ahoy_email"
19
19
  ```
20
20
 
21
21
  ## Getting Started
@@ -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
@@ -223,7 +230,7 @@ AhoyEmail.api = true
223
230
  Add this line to your application’s Gemfile:
224
231
 
225
232
  ```ruby
226
- gem 'redis'
233
+ gem "redis"
227
234
  ```
228
235
 
229
236
  And create `config/initializers/ahoy_email.rb` with:
@@ -25,6 +25,9 @@ module Ahoy
25
25
  expected_signature = AhoyEmail::Utils.signature(token: token, campaign: campaign, url: url)
26
26
  end
27
27
 
28
+ redirect_options = {}
29
+ redirect_options[:allow_other_host] = true if ActionPack::VERSION::MAJOR >= 7
30
+
28
31
  if ActiveSupport::SecurityUtils.secure_compare(signature, expected_signature)
29
32
  data = {}
30
33
  data[:campaign] = campaign if campaign
@@ -33,10 +36,10 @@ module Ahoy
33
36
  data[:controller] = self
34
37
  AhoyEmail::Utils.publish(:click, data)
35
38
 
36
- redirect_to url
39
+ redirect_to url, **redirect_options
37
40
  else
38
41
  if AhoyEmail.invalid_redirect_url
39
- redirect_to AhoyEmail.invalid_redirect_url
42
+ redirect_to AhoyEmail.invalid_redirect_url, **redirect_options
40
43
  else
41
44
  render plain: "Link expired", status: :not_found
42
45
  end
@@ -9,17 +9,17 @@ module AhoyEmail
9
9
 
10
10
  def track_send(event)
11
11
  campaign_prefix = campaign_key(event[:campaign])
12
- redis.pipelined do
13
- redis.incr("#{campaign_prefix}:sends")
14
- redis.sadd(campaigns_key, event[:campaign])
12
+ pipelined do |pipeline|
13
+ pipeline.incr("#{campaign_prefix}:sends")
14
+ pipeline.sadd(campaigns_key, event[:campaign])
15
15
  end
16
16
  end
17
17
 
18
18
  def track_click(event)
19
19
  campaign_prefix = campaign_key(event[:campaign])
20
- redis.pipelined do
21
- redis.incr("#{campaign_prefix}:clicks")
22
- redis.pfadd("#{campaign_prefix}:unique_clicks", event[:token])
20
+ pipelined do |pipeline|
21
+ pipeline.incr("#{campaign_prefix}:clicks")
22
+ pipeline.pfadd("#{campaign_prefix}:unique_clicks", event[:token])
23
23
  end
24
24
  end
25
25
 
@@ -62,10 +62,10 @@ module AhoyEmail
62
62
  unique_clicks = nil
63
63
 
64
64
  campaign_prefix = campaign_key(campaign)
65
- redis.pipelined do
66
- sends = redis.get("#{campaign_prefix}:sends")
67
- clicks = redis.get("#{campaign_prefix}:clicks")
68
- unique_clicks = redis.pfcount("#{campaign_prefix}:unique_clicks")
65
+ pipelined do |pipeline|
66
+ sends = pipeline.get("#{campaign_prefix}:sends")
67
+ clicks = pipeline.get("#{campaign_prefix}:clicks")
68
+ unique_clicks = pipeline.pfcount("#{campaign_prefix}:unique_clicks")
69
69
  end
70
70
 
71
71
  {
@@ -75,5 +75,17 @@ module AhoyEmail
75
75
  ctr: 100 * unique_clicks.value / sends.value.to_f
76
76
  }
77
77
  end
78
+
79
+ def pipelined
80
+ if Redis::VERSION.to_f >= 4.6
81
+ redis.pipelined do |pipeline|
82
+ yield pipeline
83
+ end
84
+ else
85
+ redis.pipelined do
86
+ yield redis
87
+ end
88
+ end
89
+ end
78
90
  end
79
91
  end
@@ -1,3 +1,3 @@
1
1
  module AhoyEmail
2
- VERSION = "2.1.0"
2
+ VERSION = "2.1.3"
3
3
  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", lockbox_method: lockbox_method
23
+ when "activerecord"
24
+ template "model_activerecord.rb", "app/models/ahoy/message.rb"
19
25
  end
20
26
  end
21
27
 
@@ -24,15 +30,38 @@ 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
57
+ end
58
+
59
+ def lockbox_method
60
+ if defined?(Lockbox::VERSION) && Lockbox::VERSION.to_i < 1
61
+ "encrypts"
62
+ else
63
+ "has_encrypted"
64
+ end
36
65
  end
37
66
  end
38
67
  end
@@ -6,13 +6,41 @@ 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", lockbox_method: lockbox_method
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
34
+ else
35
+ abort "Error: encryption must be lockbox or none"
36
+ end
37
+ end
38
+
39
+ def lockbox_method
40
+ if defined?(Lockbox::VERSION) && Lockbox::VERSION.to_i < 1
41
+ "encrypts"
14
42
  else
15
- template "mongoid_encrypted.rb", "app/models/ahoy/message.rb"
43
+ "has_encrypted"
16
44
  end
17
45
  end
18
46
  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,6 @@ class Ahoy::Message < ActiveRecord::Base
3
3
 
4
4
  belongs_to :user, polymorphic: true, optional: true
5
5
 
6
- encrypts :to
6
+ <%= lockbox_method %> :to
7
7
  blind_index :to
8
8
  end
@@ -11,6 +11,6 @@ class Ahoy::Message
11
11
 
12
12
  index({to_bidx: 1})
13
13
 
14
- encrypts :to
14
+ <%= lockbox_method %> :to
15
15
  blind_index :to
16
16
  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.1.0
4
+ version: 2.1.3
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-09-25 00:00:00.000000000 Z
11
+ date: 2022-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionmailer
@@ -99,9 +99,10 @@ files:
99
99
  - lib/generators/ahoy/messages/activerecord_generator.rb
100
100
  - lib/generators/ahoy/messages/mongoid_generator.rb
101
101
  - lib/generators/ahoy/messages/templates/migration.rb.tt
102
- - 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
103
104
  - lib/generators/ahoy/messages/templates/mongoid.rb.tt
104
- - lib/generators/ahoy/messages/templates/mongoid_encrypted.rb.tt
105
+ - lib/generators/ahoy/messages/templates/mongoid_lockbox.rb.tt
105
106
  - lib/generators/ahoy/messages_generator.rb
106
107
  homepage: https://github.com/ankane/ahoy_email
107
108
  licenses:
@@ -122,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
123
  - !ruby/object:Gem::Version
123
124
  version: '0'
124
125
  requirements: []
125
- rubygems_version: 3.2.22
126
+ rubygems_version: 3.3.7
126
127
  signing_key:
127
128
  specification_version: 4
128
129
  summary: First-party email analytics for Rails