studio-engine 0.5.2 → 0.5.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 +4 -4
- data/CHANGELOG.md +10 -0
- data/app/controllers/magic_links_controller.rb +1 -1
- data/app/controllers/registrations_controller.rb +1 -1
- data/app/jobs/studio/email_delivery_job.rb +9 -0
- data/app/models/studio/email_delivery.rb +46 -0
- data/db/migrate/20260614000000_create_studio_email_deliveries.rb +22 -0
- data/lib/studio/email.rb +45 -0
- data/lib/studio/version.rb +1 -1
- data/lib/studio.rb +2 -1
- data/studio-engine.gemspec +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8a6751151b77737dbf25bd04a59d9ad3f801ec8f66c214dc5a97ef5f006b1f6
|
|
4
|
+
data.tar.gz: f0283ba8e4e38b8e2375b563b6f93917c3ffbc3a0880353c62ec2c5f9441b6f4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a911d76518bba342d65e2e5cb1d32c80f28a484057deb8ea630a2aae34867a530b51f0814abedee21267ff66a03df2c71e4c5610b24248e8cb5174b289f92da5
|
|
7
|
+
data.tar.gz: '09a3b96acf18c3cd876463445eb02f704b25292f048006be18c44aeaffe2e9e152d1f42977bad66cde5834c87a0eda05489ebbf1b53cdb8c7ab6ca1f5a1d3d7b'
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,16 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
|
|
|
6
6
|
|
|
7
7
|
No entries yet.
|
|
8
8
|
|
|
9
|
+
## v0.5.3 (2026-06-14)
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **`Studio::Email.deliver`** — shared ActionMailer delivery entry point that uses an app-level `EmailDelivery` when present, the engine's namespaced durable outbox when installed, and raw `deliver_later` as a fallback.
|
|
13
|
+
- **`Studio::EmailDelivery` / `Studio::EmailDeliveryJob`** — namespaced durable delivery rows for apps that want shared audit, retry, and resend recovery without colliding with an existing top-level `EmailDelivery` model.
|
|
14
|
+
- **`studio_email_deliveries` migration template** — installable shared outbox table for new or migrating consumer apps.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Engine magic-link and passwordless signup controllers now send through `Studio::Email.deliver` instead of calling `deliver_later` directly.
|
|
18
|
+
|
|
9
19
|
## v0.5.2 (2026-06-13)
|
|
10
20
|
|
|
11
21
|
### Added
|
|
@@ -22,7 +22,7 @@ class MagicLinksController < ApplicationController
|
|
|
22
22
|
email = params[:email].to_s.strip.downcase
|
|
23
23
|
if email.match?(URI::MailTo::EMAIL_REGEXP)
|
|
24
24
|
token = MagicLink.generate(email: email, return_to: safe_path(params[:return_to]))
|
|
25
|
-
UserMailer
|
|
25
|
+
Studio::Email.deliver(UserMailer, :magic_link, email, token, to: email)
|
|
26
26
|
end
|
|
27
27
|
respond_to do |format|
|
|
28
28
|
format.json { render json: { success: true } }
|
|
@@ -14,7 +14,7 @@ class RegistrationsController < ApplicationController
|
|
|
14
14
|
email = (params.dig(:user, :email) || params[:email]).to_s.strip.downcase
|
|
15
15
|
if email.match?(URI::MailTo::EMAIL_REGEXP)
|
|
16
16
|
token = MagicLink.generate(email: email)
|
|
17
|
-
UserMailer
|
|
17
|
+
Studio::Email.deliver(UserMailer, :magic_link, email, token, to: email)
|
|
18
18
|
end
|
|
19
19
|
return redirect_to login_path, notice: "Check your inbox — we just emailed you a sign-in link."
|
|
20
20
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Studio
|
|
2
|
+
class EmailDelivery < ApplicationRecord
|
|
3
|
+
self.table_name = "studio_email_deliveries"
|
|
4
|
+
|
|
5
|
+
belongs_to :user, optional: true
|
|
6
|
+
|
|
7
|
+
scope :unsent, -> { where(sent: false) }
|
|
8
|
+
scope :recent, -> { order(created_at: :desc) }
|
|
9
|
+
|
|
10
|
+
def self.available?
|
|
11
|
+
connection.data_source_exists?(table_name)
|
|
12
|
+
rescue ActiveRecord::ActiveRecordError, NoMethodError
|
|
13
|
+
false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.deliver(mailer, action, *args, to:, user: nil, **kwargs)
|
|
17
|
+
record = create!(
|
|
18
|
+
mailer: mailer.to_s,
|
|
19
|
+
action: action.to_s,
|
|
20
|
+
email_key: "#{mailer}##{action}",
|
|
21
|
+
to: to.to_s,
|
|
22
|
+
user: user,
|
|
23
|
+
args: ActiveJob::Arguments.serialize(args),
|
|
24
|
+
kwargs: ActiveJob::Arguments.serialize([kwargs]).first
|
|
25
|
+
)
|
|
26
|
+
Studio::EmailDeliveryJob.perform_later(record.id)
|
|
27
|
+
record
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def deliver_now!
|
|
31
|
+
return if sent?
|
|
32
|
+
|
|
33
|
+
pos = ActiveJob::Arguments.deserialize(args)
|
|
34
|
+
kw = ActiveJob::Arguments.deserialize([kwargs]).first.symbolize_keys
|
|
35
|
+
mailer.constantize.public_send(action, *pos, **kw).deliver_now
|
|
36
|
+
update!(sent: true, sent_at: Time.current, error: nil)
|
|
37
|
+
rescue StandardError => e
|
|
38
|
+
update(error: e.message.to_s.first(500))
|
|
39
|
+
raise
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.resend_unsent!
|
|
43
|
+
unsent.find_each { |delivery| Studio::EmailDeliveryJob.perform_later(delivery.id) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CreateStudioEmailDeliveries < ActiveRecord::Migration[7.2]
|
|
2
|
+
def change
|
|
3
|
+
create_table :studio_email_deliveries do |t|
|
|
4
|
+
t.string :email_key, null: false
|
|
5
|
+
t.string :to
|
|
6
|
+
t.string :mailer, null: false
|
|
7
|
+
t.string :action, null: false
|
|
8
|
+
t.jsonb :args, null: false, default: []
|
|
9
|
+
t.jsonb :kwargs, null: false, default: {}
|
|
10
|
+
t.boolean :sent, null: false, default: false
|
|
11
|
+
t.datetime :sent_at
|
|
12
|
+
t.text :error
|
|
13
|
+
t.references :user, foreign_key: true
|
|
14
|
+
|
|
15
|
+
t.timestamps
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
add_index :studio_email_deliveries, :sent
|
|
19
|
+
add_index :studio_email_deliveries, :email_key
|
|
20
|
+
add_index :studio_email_deliveries, :created_at
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/studio/email.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Studio
|
|
4
|
+
module Email
|
|
5
|
+
class << self
|
|
6
|
+
# Shared email send entry point for Studio apps.
|
|
7
|
+
#
|
|
8
|
+
# Apps with an existing top-level EmailDelivery model keep using it through
|
|
9
|
+
# this facade. Apps that have installed the engine outbox migration use the
|
|
10
|
+
# namespaced Studio::EmailDelivery model. Apps without either still send via
|
|
11
|
+
# ActionMailer's normal deliver_later path.
|
|
12
|
+
def deliver(mailer, action, *args, to:, user: nil, **kwargs)
|
|
13
|
+
if (adapter = app_delivery_adapter)
|
|
14
|
+
return adapter.deliver(mailer, action, *args, to: to, user: user, **kwargs)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if (adapter = studio_delivery_adapter)
|
|
18
|
+
return adapter.deliver(mailer, action, *args, to: to, user: user, **kwargs)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
mailer.public_send(action, *args, **kwargs).deliver_later
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def app_delivery_adapter
|
|
27
|
+
return unless Object.const_defined?(:EmailDelivery, false)
|
|
28
|
+
|
|
29
|
+
adapter = Object.const_get(:EmailDelivery, false)
|
|
30
|
+
adapter if adapter.respond_to?(:deliver)
|
|
31
|
+
rescue NameError
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def studio_delivery_adapter
|
|
36
|
+
return unless Studio.const_defined?(:EmailDelivery, false)
|
|
37
|
+
|
|
38
|
+
adapter = Studio.const_get(:EmailDelivery, false)
|
|
39
|
+
adapter if adapter.respond_to?(:available?) && adapter.available?
|
|
40
|
+
rescue NameError
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/lib/studio/version.rb
CHANGED
data/lib/studio.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "studio/theme_resolver"
|
|
|
5
5
|
require "studio/username_generator"
|
|
6
6
|
require "studio/s3"
|
|
7
7
|
require "studio/image_cache"
|
|
8
|
+
require "studio/email"
|
|
8
9
|
require "studio/mail_transport"
|
|
9
10
|
|
|
10
11
|
module Studio
|
|
@@ -37,7 +38,7 @@ module Studio
|
|
|
37
38
|
mattr_accessor :draw_auth_routes, default: true
|
|
38
39
|
|
|
39
40
|
# Default From: for engine-sent mail (magic links). Apps set this to their
|
|
40
|
-
# verified
|
|
41
|
+
# verified sending address in config/initializers/studio.rb.
|
|
41
42
|
mattr_accessor :mailer_from, default: nil
|
|
42
43
|
|
|
43
44
|
# Theme role colors (7 roles)
|
data/studio-engine.gemspec
CHANGED
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
"changelog_uri" => "https://github.com/amcritchie/studio-engine/blob/main/CHANGELOG.md"
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
spec.files = Dir["lib/**/*", "app/**/*", "config/**/*", "tailwind/**/*", "Gemfile", "studio-engine.gemspec", "README.md", "CHANGELOG.md", "LICENSE"]
|
|
21
|
+
spec.files = Dir["lib/**/*", "app/**/*", "config/**/*", "db/**/*", "tailwind/**/*", "Gemfile", "studio-engine.gemspec", "README.md", "CHANGELOG.md", "LICENSE"]
|
|
22
22
|
spec.require_paths = ["lib"]
|
|
23
23
|
|
|
24
24
|
spec.add_dependency "rails", ">= 7.0", "< 8.0"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: studio-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
@@ -153,6 +153,7 @@ files:
|
|
|
153
153
|
- app/controllers/theme_settings_controller.rb
|
|
154
154
|
- app/helpers/studio_theme_helper.rb
|
|
155
155
|
- app/jobs/error_log_cleanup_job.rb
|
|
156
|
+
- app/jobs/studio/email_delivery_job.rb
|
|
156
157
|
- app/mailers/application_mailer.rb
|
|
157
158
|
- app/mailers/user_mailer.rb
|
|
158
159
|
- app/models/concerns/sluggable.rb
|
|
@@ -160,6 +161,7 @@ files:
|
|
|
160
161
|
- app/models/error_log.rb
|
|
161
162
|
- app/models/image_cache.rb
|
|
162
163
|
- app/models/session_context.rb
|
|
164
|
+
- app/models/studio/email_delivery.rb
|
|
163
165
|
- app/models/theme_setting.rb
|
|
164
166
|
- app/services/google_oauth_validator.rb
|
|
165
167
|
- app/services/magic_link.rb
|
|
@@ -199,9 +201,11 @@ files:
|
|
|
199
201
|
- app/views/theme_settings/edit.html.erb
|
|
200
202
|
- app/views/user_mailer/magic_link.html.erb
|
|
201
203
|
- app/views/user_mailer/magic_link.text.erb
|
|
204
|
+
- db/migrate/20260614000000_create_studio_email_deliveries.rb
|
|
202
205
|
- lib/studio-engine.rb
|
|
203
206
|
- lib/studio.rb
|
|
204
207
|
- lib/studio/color_scale.rb
|
|
208
|
+
- lib/studio/email.rb
|
|
205
209
|
- lib/studio/engine.rb
|
|
206
210
|
- lib/studio/image_cache.rb
|
|
207
211
|
- lib/studio/mail_transport.rb
|