Skip to content

Commit

Permalink
Make the preview url configurable (AlchemyCMS#1803)
Browse files Browse the repository at this point in the history
* Make the preview url configurable

By default Alchemy uses its internal page preview renderer,
but you can configure it now to be any URL instead.

Basic Auth is supported as well.

Example config/alchemy/config.yml

    preview:
      host: https://www.my-static-site.com
      auth:
        username: <%= ENV["BASIC_AUTH_USERNAME"] %>
        password: <%= ENV["BASIC_AUTH_PASSWORD"] %>

This is great for static sites.

* Satisfy the Hound
  • Loading branch information
tvdeyen authored Apr 30, 2020
1 parent 1e95b31 commit 7596a48
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 3 deletions.
1 change: 1 addition & 0 deletions app/controllers/alchemy/admin/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def edit
elsif page_needs_lock?
@page.lock_to!(current_alchemy_user)
end
@preview_url = Alchemy::Admin::PREVIEW_URL.url_for(@page)
@layoutpage = @page.layoutpage?
end

Expand Down
2 changes: 1 addition & 1 deletion app/views/alchemy/admin/pages/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
}
});

Alchemy.PreviewWindow.init('<%= admin_page_path(@page) %>');
Alchemy.PreviewWindow.init('<%= @preview_url %>');

$('#preview_size').bind('open.selectBoxIt', function (e) {
$('#top_menu').css('z-index', 5000);
Expand Down
13 changes: 13 additions & 0 deletions config/alchemy/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ url_nesting: true
# In Alchemy's Admin, change how many items you would get shown per page by Kaminari
items_per_page: 15

# === Preview window URL configuration
#
# By default Alchemy uses its internal page preview renderer,
# but you can configure it to be any URL instead.
#
# Basic Auth is supported.
#
# preview:
# host: https://www.my-static-site.com
# auth:
# username: <%= ENV["BASIC_AUTH_USERNAME"] %>
# password: <%= ENV["BASIC_AUTH_PASSWORD"] %>

# === Picture rendering settings
#
# Alchemy uses Dragonfly to render images. Use {size: "XXXxYYY", crop: BOOLEAN [true]} to resize images.
Expand Down
64 changes: 64 additions & 0 deletions lib/alchemy/admin/preview_url.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

require "uri"

module Alchemy
module Admin
# = Preview window URL configuration
#
# By default Alchemy uses its internal page preview renderer,
# but you can configure it to be any URL instead.
#
# Basic Auth is supported.
#
# == Example config/alchemy/config.yml
#
# preview:
# host: https://www.my-static-site.com
# auth:
# username: <%= ENV["BASIC_AUTH_USERNAME"] %>
# password: <%= ENV["BASIC_AUTH_PASSWORD"] %>
#
class PreviewUrl
class MissingProtocolError < StandardError; end

def initialize(routes:)
@routes = routes.url_helpers
@preview_config = Alchemy::Config.get(:preview)
end

def url_for(page)
if preview_config
uri_class.build(
host: uri.host,
path: "/#{page.urlname}",
userinfo: userinfo,
).to_s
else
routes.admin_page_path(page)
end
end

private

attr_reader :preview_config, :routes

def uri
URI(preview_config["host"])
end

def uri_class
if uri.class == URI::Generic
raise MissingProtocolError, "Please provide the protocol with preview['host']"
else
uri.class
end
end

def userinfo
auth = preview_config["auth"]
auth ? "#{auth["username"]}:#{auth["password"]}" : nil
end
end
end
end
9 changes: 7 additions & 2 deletions lib/alchemy/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ class Engine < Rails::Engine
Alchemy::LOOKUP_CONTEXT = ActionView::LookupContext.new(Rails.root.join("app", "views", "alchemy"))
end

initializer "alchemy.admin.preview_url" do
Alchemy::Admin::PREVIEW_URL = Alchemy::Admin::PreviewUrl.new(routes: Alchemy::Engine.routes)
end

initializer "alchemy.dependency_tracker" do
[:erb, :slim, :haml].each do |handler|
ActionView::DependencyTracker.register_tracker(handler, CacheDigests::TemplateTracker)
Expand Down Expand Up @@ -39,9 +43,10 @@ class Engine < Rails::Engine
if Rails.env.development?
initializer "alchemy.webpacker.proxy" do |app|
app.middleware.insert_before(
0, Webpacker::DevServerProxy,
0,
Webpacker::DevServerProxy,
ssl_verify_none: true,
webpacker: Alchemy.webpacker
webpacker: Alchemy.webpacker,
)
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/alchemy_cms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module Alchemy
# Require globally used Alchemy mixins
require_relative "alchemy/ability_helper"
require_relative "alchemy/admin/locale"
require_relative "alchemy/admin/preview_url"
require_relative "alchemy/auth_accessors"
require_relative "alchemy/cache_digests/template_tracker"
require_relative "alchemy/config"
Expand Down
75 changes: 75 additions & 0 deletions spec/libraries/admin/preview_url_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Alchemy::Admin::PreviewUrl do
let(:preview_url) do
described_class.new(routes: Alchemy::Engine.routes)
end

describe "#url_for" do
let(:page) { create(:alchemy_page) }

subject { preview_url.url_for(page) }

context "without preview configured" do
it "returns the admin pages preview url" do
is_expected.to eq "/admin/pages/#{page.id}"
end
end

context "with preview configured" do
context "without protocol" do
before do
stub_alchemy_config(:preview, {
"host" => "www.example.com",
})
end

it "raises error" do
expect { subject }.to raise_error(Alchemy::Admin::PreviewUrl::MissingProtocolError)
end
end

context "as http url" do
before do
stub_alchemy_config(:preview, {
"host" => "http://www.example.com",
})
end

it "returns the configured preview url" do
is_expected.to eq "http://www.example.com/#{page.urlname}"
end
end

context "as https url" do
before do
stub_alchemy_config(:preview, {
"host" => "https://www.example.com",
})
end

it "returns the configured preview url with https" do
is_expected.to eq "https://www.example.com/#{page.urlname}"
end
end

context "and with basic auth configured" do
before do
stub_alchemy_config(:preview, {
"host" => "https://www.example.com",
"auth" => {
"username" => "foo",
"password" => "baz",
},
})
end

it "returns the configured preview url with userinfo" do
is_expected.to eq "https://foo:baz@www.example.com/#{page.urlname}"
end
end
end
end
end

0 comments on commit 7596a48

Please sign in to comment.