Skip to content
Draft
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
11 changes: 11 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,14 @@ config :phoenix_live_view,

# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime

config :laboratory,
features: [
{:use_smartling_translations, "Smartling translations",
"Uses Smartling's translation workflows"}
],
cookie: [
# one month,
max_age: 3600 * 24 * 30,
http_only: true
]
12 changes: 12 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,15 @@ config :recaptcha,
http_client: Recaptcha.Http.MockClient

config :tesla, adapter: Tesla.Mock

config :laboratory,
features: [
{:test_flag, "Cool Bean", "cool bean for test"},
{:use_smartling_translations, "Smartling translations",
"Uses Smartling's translation workflows"}
],
cookie: [
# one month,
max_age: 3600 * 24 * 30,
http_only: true
]
24 changes: 24 additions & 0 deletions lib/dotcom_web/plugs/put_flags_in_assigns_hook.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule DotcomWeb.Plugs.PutFlagsInAssignsHook do
@moduledoc """
Grabs Laboratory flags from session and makes them available as assigns
"""

import Phoenix.Component

def on_mount(:default, _params, session, socket) do
flags = Application.get_env(:laboratory, :features) |> Enum.map(fn {key, _, _} -> key end)

socket =
Enum.reduce(flags, socket, fn flag, socket ->
value =
case session_value = session[Atom.to_string(flag)] do
nil -> nil
_ -> session_value
end

socket |> assign(flag, value)
end)

{:cont, socket}
end
end
30 changes: 30 additions & 0 deletions lib/dotcom_web/plugs/put_flags_in_session.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule DotcomWeb.Plugs.PutFlagsInSession do
@moduledoc """
Reads in Laboratory flags and makes them available on live view sessions.
Necessary because cookies are hard to access from LiveView.
"""
import Plug.Conn

def init(_) do
%{}
end

def call(conn, _opts) do
conn = fetch_cookies(conn)
flags = Application.get_env(:laboratory, :features) |> Enum.map(fn {key, _, _} -> key end)

Enum.reduce(flags, conn, fn flag, conn ->
value =
case conn.cookies[Atom.to_string(flag)] do
nil -> false
"true" -> true
end

conn
# Makes it available in LiveView
|> put_session(flag, value)
# Makes it available in traditional controllers
|> assign(flag, value)
end)
end
end
27 changes: 22 additions & 5 deletions lib/dotcom_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule DotcomWeb.Router do
@moduledoc false
# remove this comment, it is here to try and fix github (don't ask)
use DotcomWeb, :router

use Plug.ErrorHandler

alias DotcomWeb.ControllerHelpers
Expand All @@ -17,6 +18,10 @@ defmodule DotcomWeb.Router do
end
end

pipeline :get_flags do
plug DotcomWeb.Plugs.PutFlagsInSession
end

pipeline :secure do
if force_ssl = Application.compile_env(:dotcom, :secure_pipeline)[:force_ssl] do
plug(Plug.SSL, force_ssl)
Expand All @@ -26,6 +31,7 @@ defmodule DotcomWeb.Router do
pipeline :browser do
plug(:accepts, ["html"])
plug(:fetch_session)
plug(:get_flags)
plug(:fetch_flash)
plug(:fetch_cookies)
plug(:put_root_layout, {DotcomWeb.LayoutView, :root})
Expand Down Expand Up @@ -92,11 +98,18 @@ defmodule DotcomWeb.Router do
get("/*path", WwwRedirector, [])
end

scope "/_flags", Laboratory do
pipe_through(:browser)
forward "/", Router
end

scope "/", DotcomWeb do
import Phoenix.LiveView.Router
pipe_through([:browser, :browser_live])

live_session :alerts, layout: {DotcomWeb.LayoutView, :live} do
live_session :alerts,
layout: {DotcomWeb.LayoutView, :live},
on_mount: DotcomWeb.Plugs.PutFlagsInAssignsHook do
live("/alerts/subway", SubwayAlertsLive)
live("/alerts/commuter-rail", CommuterRailAlertsLive)
end
Expand All @@ -106,7 +119,7 @@ defmodule DotcomWeb.Router do
import Phoenix.LiveView.Router
pipe_through([:browser, :browser_live])

live_session :world_cup do
live_session :world_cup, on_mount: DotcomWeb.Plugs.PutFlagsInAssignsHook do
live "/", WorldCupTimetableLive
end
end
Expand Down Expand Up @@ -313,7 +326,9 @@ defmodule DotcomWeb.Router do
import Phoenix.LiveView.Router
pipe_through([:browser, :browser_live])

live_session :rider, layout: {DotcomWeb.LayoutView, :live} do
live_session :rider,
layout: {DotcomWeb.LayoutView, :live},
on_mount: DotcomWeb.Plugs.PutFlagsInAssignsHook do
live("/search", SearchPageLive)
live("/trip-planner", TripPlannerLive)
end
Expand All @@ -323,7 +338,7 @@ defmodule DotcomWeb.Router do
import Phoenix.LiveView.Router
pipe_through([:browser, :browser_live])

live_session :departures do
live_session :departures, on_mount: DotcomWeb.Plugs.PutFlagsInAssignsHook do
live "/", ScheduleFinderLive
end
end
Expand All @@ -332,7 +347,9 @@ defmodule DotcomWeb.Router do
import Phoenix.LiveView.Router
pipe_through([:browser, :browser_live, :basic_auth_readonly])

live_session :default, layout: {DotcomWeb.LayoutView, :preview} do
live_session :default,
layout: {DotcomWeb.LayoutView, :preview},
on_mount: DotcomWeb.Plugs.PutFlagsInAssignsHook do
live "/", PreviewLive
live "/schedules/bostonstadium", WorldCupTimetableLive
live "/stop-map", StopMapLive
Expand Down
7 changes: 4 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defmodule DotCom.Mixfile do
start_permanent: Mix.env() == :prod,
test_coverage: [tool: ExCoveralls],
dialyzer: [
plt_add_apps: [:mix, :phoenix_live_reload, :mbta_metro],
plt_add_apps: [:mix, :phoenix_live_reload, :mbta_metro, :laboratory],
flags: [:unmatched_returns]
],
deps: deps(),
Expand Down Expand Up @@ -73,7 +73,7 @@ defmodule DotCom.Mixfile do
mod: {Dotcom.Application, []},
# a list of OTP applications your application depends on which are not included in :deps
extra_applications: extra_apps,
included_applications: [:mbta_metro]
included_applications: [:mbta_metro, :laboratory]
]
end

Expand Down Expand Up @@ -177,7 +177,8 @@ defmodule DotCom.Mixfile do
{:uuid, "1.1.8"},
{:wallaby, "0.30.12", [runtime: false, only: [:dev, :test]]},
{:yaml_elixir, "2.12.1", only: [:dev]},
{:ymlr, "5.1.4", only: [:dev]}
{:ymlr, "5.1.4", only: [:dev]},
{:laboratory, [github: "lilybarrett/laboratory", ref: "update_cowboy_version"]}
]
end
end
3 changes: 2 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"content_security_policy": {:git, "https://github.com/unill-io/content_security_policy.git", "921fdb9693f68996299af0f6a52288932d3d27c0", [tag: "v1.1.1"]},
"cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"},
"cowboy": {:hex, :cowboy, "2.14.2", "4008be1df6ade45e4f2a4e9e2d22b36d0b5aba4e20b0a0d7049e28d124e34847", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "569081da046e7b41b5df36aa359be71a0c8874e5b9cff6f747073fc57baf1ab9"},
"cowboy": {:hex, :cowboy, "2.15.0", "9cfe86ed7117bf045e10adbedb0170af7be57f2a3637e7be143433d8dd267396", [:make, :rebar3], [{:cowlib, ">= 2.16.0 and < 3.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, ">= 1.8.0 and < 3.0.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "179fb65140fb440a17b767ad53b755081506f9596c4db5c49c0396d8c8643668"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
"cowlib": {:hex, :cowlib, "2.16.0", "54592074ebbbb92ee4746c8a8846e5605052f29309d3a873468d76cdf932076f", [:make, :rebar3], [], "hexpm", "7f478d80d66b747344f0ea7708c187645cfcc08b11aa424632f78e25bf05db51"},
"crc": {:hex, :crc, "0.10.6", "a52243715da06265399ade929b12e6807a82ddbd04231d8bd3069480aa890f01", [:mix, :rebar3], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "9e832833d48a5fff03cb7488f8aa5c08adda0a5fa8188bbe124cb17c4e39a00d"},
Expand Down Expand Up @@ -70,6 +70,7 @@
"iso8601": {:hex, :iso8601, "1.3.4", "7b1f095f86f6cf65e1e5a77872e8e8bf69bd58d4c3a415b3f77d9cc9423ecbb9", [:rebar3], [], "hexpm", "a334469c07f1c219326bc891a95f5eec8eb12dd8071a3fff56a7843cb20fae34"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"jsx": {:hex, :jsx, "3.1.0", "d12516baa0bb23a59bb35dccaf02a1bd08243fcbb9efe24f2d9d056ccff71268", [:rebar3], [], "hexpm", "0c5cc8fdc11b53cc25cf65ac6705ad39e54ecc56d1c22e4adb8f5a53fb9427f3"},
"laboratory": {:git, "https://github.com/lilybarrett/laboratory.git", "af848bd59563ccb6aa014415d674693e5a8c0e50", [ref: "update_cowboy_version"]},
"lazy_html": {:hex, :lazy_html, "0.1.10", "ffe42a0b4e70859cf21a33e12a251e0c76c1dff76391609bd56702a0ef5bc429", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "50f67e5faa09d45a99c1ddf3fac004f051997877dc8974c5797bb5ccd8e27058"},
"live_isolated_component": {:hex, :live_isolated_component, "0.10.0", "e38b0b8dc5ff39f1d581fa2a05c7928d0475a854e246aee87fc2bc22726ff356", [:mix], [{:phoenix, "~> 1.7.0 or ~> 1.8.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0.0 or ~> 1.1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "170bb70fa89db7e94f95407523352cd619d0f17886017c188f93cfe728550725"},
"logster": {:hex, :logster, "1.1.1", "d6fddac540dd46adde0c894024500867fe63b0043713f842c62da5815e21db10", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d18e852c430812ad1c9756998ebe46ec814c724e6eb551a512d7e3f8dee24cef"},
Expand Down
32 changes: 32 additions & 0 deletions test/dotcom_web/plugs/put_flags_in_session_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule DotcomWeb.Plugs.PutFlagsInSessionTest do
use DotcomWeb.ConnCase, async: true

import DotcomWeb.Plugs.PutFlagsInSession

describe "Put Flags in Session Plug" do
test "flag is false if it has not been set", %{conn: conn} do
conn =
conn
|> Plug.Test.init_test_session(%{})
|> fetch_session()
|> bypass_through(DotcomWeb.Router, :get_flags)
|> get("/")

assert conn.assigns.test_flag == false
assert conn.private.plug_session["test_flag"] == false
end

test "flag is true if it has been set", %{conn: conn} do
conn =
conn
|> put_resp_cookie("test_flag", "true")
|> Plug.Test.init_test_session(%{})
|> fetch_session()
|> bypass_through(DotcomWeb.Router, :get_flags)
|> get("/")

assert conn.assigns.test_flag == true
assert conn.private.plug_session["test_flag"] == true
end
end
end
Loading