Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embeddable mode #213 #5

Merged
merged 1 commit into from
Jan 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ ENVIRONMENT=dev
MAILER_ADAPTER=Bamboo.LocalAdapter
LOG_LEVEL=debug
SELFHOST=false
## Uncomment the next line to permit embedding mode
#SESSION_EXTRA=SameSite=None;Secure
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ MAILER_ADAPTER=Bamboo.TestAdapter
[email protected]
ADMIN_USER_PWD=fakepassword
SELFHOST=false
## Uncomment the next line to permit embedding mode
#SESSION_EXTRA=SameSite=None;Secure
5 changes: 4 additions & 1 deletion config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ end

secret_key_base = System.fetch_env!("SECRET_KEY_BASE")

session_extra = System.get_env("SESSION_EXTRA", "SameSite=Lax")

db_url =
System.get_env(
"DATABASE_URL",
Expand Down Expand Up @@ -86,7 +88,8 @@ config :plausible, :selfhost,
config :plausible, PlausibleWeb.Endpoint,
url: [host: base_url.host, scheme: base_url.scheme, port: base_url.port],
http: [port: port],
secret_key_base: secret_key_base
secret_key_base: secret_key_base,
session_extra: session_extra

config :plausible, Plausible.Repo, url: db_url

Expand Down
9 changes: 9 additions & 0 deletions lib/plausible/site/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Plausible.Site do
field :domain, :string
field :timezone, :string
field :public, :boolean
field :embeddable, :boolean

many_to_many :members, User, join_through: Plausible.Site.Membership
has_one :google_auth, GoogleAuth
Expand Down Expand Up @@ -38,6 +39,14 @@ defmodule Plausible.Site do
change(site, public: false)
end

def make_embeddable(site) do
change(site, embeddable: true)
end

def make_not_embeddable(site) do
change(site, embeddable: false)
end

defp clean_domain(changeset) do
clean_domain =
(get_field(changeset, :domain) || "")
Expand Down
22 changes: 22 additions & 0 deletions lib/plausible_web/controllers/site_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,28 @@ defmodule PlausibleWeb.SiteController do
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
end

def make_embeddable(conn, %{"website" => website}) do
site =
Sites.get_for_user!(conn.assigns[:current_user].id, website)
|> Plausible.Site.make_embeddable()
|> Repo.update!()

conn
|> put_flash(:success, "Stats for #{site.domain} are now embeddable.")
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
end

def make_not_embeddable(conn, %{"website" => website}) do
site =
Sites.get_for_user!(conn.assigns[:current_user].id, website)
|> Plausible.Site.make_not_embeddable()
|> Repo.update!()

conn
|> put_flash(:success, "Stats for #{site.domain} are now not embeddable.")
|> redirect(to: "/#{URI.encode_www_form(site.domain)}/settings/visibility")
end

def enable_weekly_report(conn, %{"website" => website}) do
site = Sites.get_for_user!(conn.assigns[:current_user].id, website)

Expand Down
18 changes: 16 additions & 2 deletions lib/plausible_web/controllers/stats_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ defmodule PlausibleWeb.StatsController do

plug PlausibleWeb.AuthorizeStatsPlug when action in [:stats, :csv_export]
plug PlausibleWeb.UpgradeBillingPlug when action in [:stats]
plug PlausibleWeb.EmbeddableStatsPlug when action in [:stats]
plug PlausibleWeb.EmbeddableAuthSharedLinkPlug when action in [:shared_link, :authenticate_shared_link]

def base_domain() do
PlausibleWeb.Endpoint.host()
Expand All @@ -22,6 +24,7 @@ defmodule PlausibleWeb.StatsController do
|> put_resp_header("x-robots-tag", "noindex")
|> render("stats.html",
site: site,
embed_mode: get_session(conn, "embed_mode"),
has_goals: Plausible.Sites.has_goals?(site),
title: "Plausible · " <> site.domain,
offer_email_report: offer_email_report,
Expand All @@ -30,7 +33,10 @@ defmodule PlausibleWeb.StatsController do
else
conn
|> assign(:skip_plausible_tracking, true)
|> render("waiting_first_pageview.html", site: site)
|> render("waiting_first_pageview.html",
site: site,
embed_mode: get_session(conn, "embed_mode")
)
end
end

Expand Down Expand Up @@ -64,16 +70,24 @@ defmodule PlausibleWeb.StatsController do
Repo.get_by(Plausible.Site.SharedLink, slug: slug)
|> Repo.preload(:site)

embed_mode = (Enum.at(conn.path_info, 1) == "embed")

embed_link = if embed_mode do "/embed" else "" end

if shared_link do
if shared_link.password_hash do
conn
|> put_session("embed_mode", embed_mode)
|> assign(:skip_plausible_tracking, true)
|> render("shared_link_password.html",
link: shared_link,
embed_link: embed_link,
layout: {PlausibleWeb.LayoutView, "focus.html"}
)
else
shared_link_auth_success(conn, shared_link)
conn
|> put_session("embed_mode", embed_mode)
|> shared_link_auth_success(shared_link)
end
else
render_error(conn, 404)
Expand Down
2 changes: 1 addition & 1 deletion lib/plausible_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule PlausibleWeb.Endpoint do
signing_salt: "3IL0ob4k",
# 5 years, this is super long but the SlidingSessionTimeout will log people out if they don't return for 2 weeks
max_age: 60 * 60 * 24 * 365 * 5,
extra: "SameSite=Lax"
extra: config[:session_extra]

plug CORSPlug
plug PlausibleWeb.Tracker
Expand Down
27 changes: 27 additions & 0 deletions lib/plausible_web/plugs/embeddable_auth_shared_link_plug.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule PlausibleWeb.EmbeddableAuthSharedLinkPlug do
import Plug.Conn
use Plausible.Repo

def init(options) do
options
end

def call(conn, _opts) do
shared_link =
Repo.get_by(Plausible.Site.SharedLink, slug: conn.params["slug"])
|> Repo.preload(:site)

if !shared_link || !shared_link.site do
PlausibleWeb.ControllerHelpers.render_error(conn, 404) |> halt
else
if (!shared_link.site.embeddable) || (Enum.at(conn.path_info, 1) != "embed") do
assign(conn, :shared_link, shared_link)
else
conn
|> put_resp_header("x-frame-options", "allow-from " <> shared_link.site.domain)
|> put_resp_header("content-security-policy", "frame-ancestors " <> shared_link.site.domain)
|> assign(:shared_link, shared_link)
end
end
end
end
23 changes: 23 additions & 0 deletions lib/plausible_web/plugs/embeddable_stats_plug.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule PlausibleWeb.EmbeddableStatsPlug do
import Plug.Conn
use Plausible.Repo

def init(options) do
options
end

def call(%{assigns: %{site: site}} = conn, _opts) do
if !site do
PlausibleWeb.ControllerHelpers.render_error(conn, 404) |> halt
else
if !site.embeddable || !get_session(conn, "embed_mode") do
assign(conn, :site, site)
else
conn
|> put_resp_header("x-frame-options", "allow-from " <> site.domain)
|> put_resp_header("content-security-policy", "frame-ancestors " <> site.domain)
|> assign(:site, site)
end
end
end
end
4 changes: 4 additions & 0 deletions lib/plausible_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ defmodule PlausibleWeb.Router do
post "/sites", SiteController, :create_site
post "/sites/:website/make-public", SiteController, :make_public
post "/sites/:website/make-private", SiteController, :make_private
post "/sites/:website/make-embeddable", SiteController, :make_embeddable
post "/sites/:website/make-not-embeddable", SiteController, :make_not_embeddable
post "/sites/:website/weekly-report/enable", SiteController, :enable_weekly_report
post "/sites/:website/weekly-report/disable", SiteController, :disable_weekly_report
post "/sites/:website/weekly-report/recipients", SiteController, :add_weekly_report_recipient
Expand Down Expand Up @@ -177,7 +179,9 @@ defmodule PlausibleWeb.Router do
delete "/:website", SiteController, :delete_site
delete "/:website/stats", SiteController, :reset_stats

get "/share/embed/:slug", StatsController, :shared_link
get "/share/:slug", StatsController, :shared_link
post "/share/embed/:slug/authenticate", StatsController, :authenticate_shared_link
post "/share/:slug/authenticate", StatsController, :authenticate_shared_link
get "/:domain/visitors.csv", StatsController, :csv_export
get "/:domain/*path", StatsController, :stats
Expand Down
Loading