controllers tests are passing
This commit is contained in:
parent
aa75c224fc
commit
4225bbdf61
@ -1,4 +1,4 @@
|
||||
defmodule Bright.PatreonEntitlements do
|
||||
defmodule Bright.Patrons.PatreonEntitlements do
|
||||
@spec extract_tiers(map()) :: list(String.t())
|
||||
def extract_tiers(response_body) do
|
||||
response_body
|
@ -1,4 +1,4 @@
|
||||
defmodule Bright.TierMapper do
|
||||
defmodule Bright.Patrons.TierMapper do
|
||||
@patreon_tiers %{
|
||||
"everyone" => 0,
|
||||
"free" => 0,
|
||||
@ -34,10 +34,16 @@ defmodule Bright.TierMapper do
|
||||
|
||||
def get_tier_number(_, _), do: 0
|
||||
|
||||
def largest_tier_for_platform(_platform, []), do: 0
|
||||
@spec largest_tier_for_platform(any(), nil | maybe_improper_list()) :: any()
|
||||
def largest_tier_for_platform(platform, tier_ids)
|
||||
when is_list(tier_ids) and is_binary(platform) do
|
||||
when is_binary(platform) and is_list(tier_ids) do
|
||||
tier_ids
|
||||
|> Enum.map(&get_tier_number(platform, &1))
|
||||
|> Enum.max()
|
||||
end
|
||||
|
||||
@spec largest_tier_for_platform(any(), list()) :: integer()
|
||||
def largest_tier_for_platform(_, _), do: 0
|
||||
def largest_tier_for_platform(_), do: 0
|
||||
end
|
@ -35,7 +35,7 @@ defmodule Bright.Users.User do
|
||||
"""
|
||||
def registration_changeset(user, attrs, _opts \\ []) do
|
||||
user
|
||||
|> cast(attrs, [:patreon_id, :github_id, :role])
|
||||
|> cast(attrs, [:patreon_id, :github_id, :role, :patron_tier])
|
||||
|> validate_provider_id()
|
||||
end
|
||||
|
||||
|
@ -19,6 +19,27 @@ defmodule BrightWeb.CoreComponents do
|
||||
|
||||
alias Phoenix.LiveView.JS
|
||||
|
||||
@doc """
|
||||
Renders an external link.
|
||||
|
||||
## Example:
|
||||
```heex
|
||||
<.external_link href="https://example.com">Visit Example</.external_link>
|
||||
```
|
||||
"""
|
||||
attr :rest, :global, doc: "the arbitrary HTML attributes to add to the flash container"
|
||||
attr :href, :string, required: true
|
||||
slot :inner_block, required: true
|
||||
|
||||
def(external_link(assigns)) do
|
||||
~H"""
|
||||
<.link href={@href} target="_blank" rel="noopener noreferrer" {@rest}>
|
||||
{render_slot(@inner_block)}
|
||||
<.icon name="arrow-up-right-from-square" class="ml-0" />
|
||||
</.link>
|
||||
"""
|
||||
end
|
||||
|
||||
@doc """
|
||||
Renders a modal.
|
||||
|
||||
|
@ -1,4 +1,81 @@
|
||||
<main class="section">
|
||||
<.flash_group flash={@flash} />
|
||||
{@inner_content}
|
||||
</main>
|
||||
<div>
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<.link href={~p"/"} class="navbar-item">
|
||||
<h1 class="title">🔞💦 Futureporn.net</h1>
|
||||
</.link>
|
||||
|
||||
<.link
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
phx-click={JS.toggle(to: ".navbar-menu")}
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<.link href={~p"/streams"} class="navbar-item">
|
||||
Streams Archive
|
||||
</.link>
|
||||
|
||||
<.link href={~p"/vods"} class="navbar-item">
|
||||
Vods
|
||||
</.link>
|
||||
|
||||
<.link href={~p"/vtubers"} class="navbar-item">
|
||||
Vtubers
|
||||
</.link>
|
||||
|
||||
<.link href={~p"/about"} class="navbar-item">
|
||||
About
|
||||
</.link>
|
||||
|
||||
<!--<.link
|
||||
href={~p"/patrons"}
|
||||
class="navbar-item">
|
||||
Patrons
|
||||
</.link>
|
||||
|
||||
<.link
|
||||
href={~p"/api"}
|
||||
class="navbar-item">
|
||||
API
|
||||
</.link>-->
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<.icon name="person-digging" class="is-unclickable" />
|
||||
<.icon name="hammer" class="is-unclickable" />
|
||||
</div>
|
||||
|
||||
<%= if @current_user do %>
|
||||
<.link href={~p"/profile"} class="navbar-item">
|
||||
Profile
|
||||
</.link>
|
||||
<.link href={~p"/auth/logout"} method="get" class="navbar-item">
|
||||
Log out
|
||||
</.link>
|
||||
<% else %>
|
||||
<.link href={~p"/auth/patreon"} method="get" class="navbar-item">
|
||||
Sign in via Patreon
|
||||
</.link>
|
||||
<p>hello</p>
|
||||
<.link href={~p"/auth/patreon"} class="navbar-item">
|
||||
Log in
|
||||
</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="container">
|
||||
<.flash_group flash={@flash} />
|
||||
{@inner_content}
|
||||
</main>
|
||||
</div>
|
||||
|
@ -28,81 +28,6 @@
|
||||
</script>
|
||||
</head>
|
||||
<body class="">
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<.link href={~p"/"} class="navbar-item">
|
||||
<h1 class="title">🔞💦 Futureporn.net</h1>
|
||||
</.link>
|
||||
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
phx-click={JS.toggle(to: ".navbar-menu")}
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<.link href={~p"/streams"} class="navbar-item">
|
||||
Streams Archive
|
||||
</.link>
|
||||
|
||||
<.link href={~p"/vods"} class="navbar-item">
|
||||
Vods
|
||||
</.link>
|
||||
|
||||
<.link href={~p"/vtubers"} class="navbar-item">
|
||||
Vtubers
|
||||
</.link>
|
||||
|
||||
<.link href={~p"/about"} class="navbar-item">
|
||||
About
|
||||
</.link>
|
||||
|
||||
<!--<.link
|
||||
href={~p"/patrons"}
|
||||
class="navbar-item">
|
||||
Patrons
|
||||
</.link>
|
||||
|
||||
<.link
|
||||
href={~p"/api"}
|
||||
class="navbar-item">
|
||||
API
|
||||
</.link>-->
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<.icon name="person-digging" class="is-unclickable" />
|
||||
<.icon name="hammer" class="is-unclickable" />
|
||||
</div>
|
||||
|
||||
<%= if @current_user do %>
|
||||
<.link href={~p"/profile"} class="navbar-item">
|
||||
Profile
|
||||
</.link>
|
||||
<.link href={~p"/auth/logout"} method="get" class="navbar-item">
|
||||
Log out
|
||||
</.link>
|
||||
<% else %>
|
||||
<.link href={~p"/auth/patreon"} method="get" class="navbar-item">
|
||||
Sign in via Patreon
|
||||
</.link>
|
||||
<p>hello</p>
|
||||
<.link href={~p"/auth/patreon"} class="navbar-item">
|
||||
Log in
|
||||
</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{@inner_content}
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,6 +4,7 @@ defmodule BrightWeb.AuthController do
|
||||
|
||||
alias Bright.Users
|
||||
alias Bright.Users.User
|
||||
alias Bright.Patrons.TierMapper
|
||||
|
||||
alias Bright.Repo
|
||||
require Logger
|
||||
@ -66,12 +67,19 @@ defmodule BrightWeb.AuthController do
|
||||
end
|
||||
end
|
||||
|
||||
def callback(conn = %{assigns: %{ueberauth_failure: fails}}, _params) do
|
||||
Logger.error(inspect(fails))
|
||||
def callback(
|
||||
conn = %{assigns: %{ueberauth_failure: %Ueberauth.Failure{errors: errors}}},
|
||||
_params
|
||||
) do
|
||||
error_messages =
|
||||
errors
|
||||
|> Enum.map(fn %Ueberauth.Failure.Error{message: message} -> message end)
|
||||
# Join multiple errors into a single string if needed
|
||||
|> Enum.join(", ")
|
||||
|
||||
conn
|
||||
|> put_flash(:error, "Something went wrong; please try again.")
|
||||
|> render("new.html", user: nil)
|
||||
|> put_flash(:error, "Authentication failed: #{error_messages}")
|
||||
|> redirect(to: ~p"/")
|
||||
end
|
||||
|
||||
defp params_from_ueberauth(%{provider: :github, info: info, uid: uid}) do
|
||||
@ -88,14 +96,15 @@ defmodule BrightWeb.AuthController do
|
||||
"getting params_from_ueberauth provider: :patreon. info=#{inspect(info)}, uid=#{inspect(uid)}, user=#{inspect(user)}"
|
||||
)
|
||||
|
||||
currently_entitled_tiers = Bright.PatreonEntitlements.extract_tiers(user)
|
||||
Logger.debug("currently_entitled_tiers=#{currently_entitled_tiers}")
|
||||
patron_tier = Bright.TierMapper.largest_tier_for_platform("patreon", currently_entitled_tiers)
|
||||
currently_entitled_tiers = Bright.Patrons.PatreonEntitlements.extract_tiers(user)
|
||||
Logger.debug("currently_entitled_tiers=#{inspect(currently_entitled_tiers)}")
|
||||
|
||||
patron_tier =
|
||||
TierMapper.largest_tier_for_platform("patreon", currently_entitled_tiers)
|
||||
|
||||
Logger.debug(">>>> computed patron_tier=#{inspect(patron_tier)}")
|
||||
|
||||
%{
|
||||
name: info.name,
|
||||
handle: info.nickname,
|
||||
patreon_handle: info.nickname,
|
||||
patreon_id: uid,
|
||||
patron_tier: patron_tier
|
||||
}
|
||||
@ -129,7 +138,7 @@ defmodule BrightWeb.AuthController do
|
||||
user = user_id && Users.get_user!(user_id)
|
||||
|
||||
Logger.debug(
|
||||
"fetch_current_user attempting to get user. user_id=#{user_id} user=#{inspect(user)}"
|
||||
"fetch_current_user attempting to get user. user_id=#{inspect(user_id)} user=#{inspect(user)}"
|
||||
)
|
||||
|
||||
assign(conn, :current_user, user)
|
||||
@ -211,6 +220,40 @@ defmodule BrightWeb.AuthController do
|
||||
end
|
||||
end
|
||||
|
||||
def require_patron_tier_1(conn, _), do: require_patron_tier(conn, 1)
|
||||
def require_patron_tier_2(conn, _), do: require_patron_tier(conn, 2)
|
||||
def require_patron_tier_3(conn, _), do: require_patron_tier(conn, 3)
|
||||
|
||||
@doc """
|
||||
Ensures the user has a patron tier of `tier_level` or higher,
|
||||
or has the role of "admin".
|
||||
|
||||
Redirects users who don't meet the requirement.
|
||||
"""
|
||||
def require_patron_tier(conn, tier_level) when is_integer(tier_level) do
|
||||
user = conn.assigns[:current_user] || %{}
|
||||
|
||||
Logger.debug(
|
||||
"require_patron_tier with conn=#{inspect(conn)} and tier_level=#{inspect(tier_level)} and user=#{inspect(user)}"
|
||||
)
|
||||
|
||||
case user do
|
||||
%{role: "admin"} ->
|
||||
conn
|
||||
|
||||
%{patron_tier: patron_tier} when is_integer(patron_tier) and patron_tier >= tier_level ->
|
||||
conn
|
||||
|
||||
_ ->
|
||||
user_return_to = conn.assigns[:user_return_to] || "/"
|
||||
|
||||
conn
|
||||
|> put_flash(:error, "This route is for tier #{tier_level} or higher.")
|
||||
|> redirect(to: user_return_to)
|
||||
|> halt()
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Used for routes that require the user to have admin privs.
|
||||
"""
|
||||
@ -219,7 +262,11 @@ defmodule BrightWeb.AuthController do
|
||||
%{role: "admin"} ->
|
||||
conn
|
||||
|
||||
_ ->
|
||||
user ->
|
||||
Logger.debug(
|
||||
"A USER IS DOING A THING THAT REQUIRES ADMIN USER. BUT WE THINK THEY ARE NOT AN ADMIN. user=#{inspect(user)}"
|
||||
)
|
||||
|
||||
conn
|
||||
|> put_flash(:error, "Only admins can do that.")
|
||||
|> maybe_store_return_to()
|
||||
|
@ -3,33 +3,34 @@ defmodule BrightWeb.PageController do
|
||||
|
||||
require Logger
|
||||
|
||||
@spec home(Plug.Conn.t(), any()) :: Plug.Conn.t()
|
||||
def home(conn, _params) do
|
||||
# The home page is often custom made,
|
||||
# so skip the default app layout.
|
||||
# render(conn, :home, layout: false)
|
||||
# render(conn, :home)
|
||||
|
||||
# render(conn, "index.html", current_user: get_session(conn, :current_user))
|
||||
# send_resp(conn, 201, "")
|
||||
conn
|
||||
|> put_status(202)
|
||||
|> render(:home, layout: false, current_user: get_session(conn, :current_user))
|
||||
|> render(:home)
|
||||
|
||||
# redirect(conn, to: ~p"/redirect_test")
|
||||
# redirect(conn, external: "https://elixir-lang.org/")
|
||||
end
|
||||
|
||||
def about(conn, _params) do
|
||||
render(conn, :about, layout: false)
|
||||
render(conn, :about)
|
||||
end
|
||||
|
||||
def api(conn, _params) do
|
||||
render(conn, :api, layout: false)
|
||||
render(conn, :api)
|
||||
end
|
||||
|
||||
def profile(conn, _params) do
|
||||
sesh = get_session(conn, :current_user)
|
||||
Logger.debug("/profile with sesh=#{inspect(sesh)} conn=#{inspect(conn)}")
|
||||
render(conn, :profile, layout: false)
|
||||
render(conn, :profile)
|
||||
end
|
||||
|
||||
def health(conn, _params) do
|
||||
@ -38,6 +39,6 @@ defmodule BrightWeb.PageController do
|
||||
end
|
||||
|
||||
def redirect_test(conn, _params) do
|
||||
render(conn, :home, layout: false)
|
||||
render(conn, :home)
|
||||
end
|
||||
end
|
||||
|
@ -20,7 +20,7 @@
|
||||
</p>
|
||||
</i>
|
||||
|
||||
<a class="mt-5 button is-primary" href={~p"/streams"}>Streams Archive</a>
|
||||
<.link class="mt-5 button is-primary" href={~p"/streams"}>Streams Archive</.link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -30,8 +30,8 @@
|
||||
<p class="subtitle is-6">Futureporn User {@current_user.id}</p>
|
||||
<p class="subtitle is-6"><i>n</i> uploads</p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec
|
||||
iaculis mauris. <a>@bulmaio</a>. <a href="#">#css</a>
|
||||
<a href="#">#responsive</a>
|
||||
iaculis mauris. <.link>@bulmaio</.link>. <.link href="#">#css</.link>
|
||||
<.link href="#">#responsive</.link>
|
||||
<br />
|
||||
<time datetime="2016-1-1">11:09 PM - 1 Jan 2016</time>
|
||||
</div>
|
||||
|
@ -2,19 +2,19 @@
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<%= if @torrent && @torrent.magnet do %>
|
||||
<a target="_blank" href={@torrent.magnet}><.icon name="magnet" class="icon" /></a>
|
||||
<.link target="_blank" href={@torrent.magnet}><.icon name="magnet" class="icon" /></.link>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<%= if @torrent && @torrent.cdn_url do %>
|
||||
<a target="_blank" href={@torrent.cdn_url} class="button">
|
||||
<.link target="_blank" href={@torrent.cdn_url} class="button">
|
||||
<span class="icon-text">
|
||||
<span class="icon">
|
||||
<.icon name="download" />
|
||||
</span>
|
||||
<span>Download</span>
|
||||
</span>
|
||||
</a>
|
||||
</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
|
@ -25,7 +25,9 @@
|
||||
>
|
||||
<p class="vjs-no-js">
|
||||
To view this video please enable JavaScript, and consider upgrading to a web browser that
|
||||
<a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
|
||||
<.link href="http://videojs.com/html5-video-support/" target="_blank">
|
||||
supports HTML5 video
|
||||
</.link>
|
||||
</p>
|
||||
</video>
|
||||
<% else %>
|
||||
@ -60,7 +62,7 @@
|
||||
<:item title="Torrent"><TorrentHTML.summary torrent={@vod.torrent} /></:item>
|
||||
<:item title="Source VOD File">
|
||||
<%= if @vod.s3_cdn_url do %>
|
||||
<a
|
||||
<.link
|
||||
class="button is-secondary"
|
||||
href={@vod.s3_cdn_url}
|
||||
download={Path.basename(@vod.s3_cdn_url)}
|
||||
@ -73,7 +75,7 @@
|
||||
Download
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</.link>
|
||||
<% end %>
|
||||
</:item>
|
||||
<:item title="HLS Playlist URL">{@vod.playlist_url}</:item>
|
||||
|
@ -14,6 +14,7 @@ defmodule BrightWeb.VtuberController do
|
||||
render(conn, :new, changeset: changeset)
|
||||
end
|
||||
|
||||
@spec create(Plug.Conn.t(), map()) :: Plug.Conn.t()
|
||||
def create(conn, %{"vtuber" => vtuber_params}) do
|
||||
case Vtubers.create_vtuber(vtuber_params) do
|
||||
{:ok, vtuber} ->
|
||||
|
@ -4,28 +4,22 @@ defmodule BrightWeb.IdenticonLive do
|
||||
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
<figure id="identicon" class="image is-48x48">
|
||||
{raw(
|
||||
IdenticonSvg.generate(assigns.identicon_seed, 5, :basic, 0.8, 2,
|
||||
squircle_curvature: 0.8
|
||||
)
|
||||
)}
|
||||
</figure>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<button
|
||||
class="button"
|
||||
phx-click={JS.push("randomize", loading: "#identicon")}
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.icon name="dice" class="icon" />
|
||||
<span>Randomize Identicon</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="button"
|
||||
phx-click={JS.push("randomize", loading: "#identicon")}
|
||||
phx-target={@myself}
|
||||
>
|
||||
<span class="icon is-small">
|
||||
<.icon name="dice" />
|
||||
</span>
|
||||
<figure id="identicon" class="icon image is-24x24 mr-2">
|
||||
{raw(
|
||||
IdenticonSvg.generate(assigns.identicon_seed, 5, :basic, 0.8, 2, squircle_curvature: 0.8)
|
||||
)}
|
||||
</figure>
|
||||
<span>Randomize Identicon</span>
|
||||
</button>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
@ -5,32 +5,134 @@ defmodule BrightWeb.ProfileLive do
|
||||
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<.header>
|
||||
Profile
|
||||
</.header>
|
||||
|
||||
<section class="section">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<.live_component
|
||||
module={BrightWeb.IdenticonLive}
|
||||
id={"user-#{@current_user.id}-identicon"}
|
||||
identicon_seed={@current_user.identicon_seed}
|
||||
/>
|
||||
<div class="columns">
|
||||
<div class="column is-half">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-left">
|
||||
<figure class="image is-48x48">
|
||||
{raw(
|
||||
IdenticonSvg.generate(@current_user.identicon_seed, 5, :basic, 0.8, 2,
|
||||
squircle_curvature: 0.8
|
||||
)
|
||||
)}
|
||||
</figure>
|
||||
</div>
|
||||
<div class="media-content">
|
||||
<p class="title is-4">User {@current_user.id}</p>
|
||||
<p class="subtitle is-6">@{@current_user.id}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<p class="title is-5 mt-5">Patron Tier</p>
|
||||
<p class="tag subtitle is-6 mt-2">{@current_user.patron_tier}</p>
|
||||
|
||||
<p class="title is-5 mt-5">Role</p>
|
||||
<p class="tag subtitle is-6 mt-2">{@current_user.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<p class="title is-4">User {@current_user.id}</p>
|
||||
|
||||
<p class="title is-5 mt-5">Patron Tier</p>
|
||||
<p class="tag subtitle is-6 mt-2">{@current_user.patron_tier}</p>
|
||||
<p>
|
||||
Change your patron tier at
|
||||
<a target="_blank" href="https://patreon.com/CJ_Clippy">patreon.com/CJ_Clippy</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-half">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Settings</p>
|
||||
</header>
|
||||
<div class="content">
|
||||
<div class="card-content">
|
||||
<.live_component
|
||||
module={BrightWeb.IdenticonLive}
|
||||
id={"user-#{@current_user.id}-identicon"}
|
||||
identicon_seed={@current_user.identicon_seed}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="hero">
|
||||
<div class="hero-body">
|
||||
<p class="title">Care to upgrade your Patron Tier?</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<table class="table is-striped is-hoverable is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Feature</th>
|
||||
<th>Tier 0</th>
|
||||
<th>Tier 1</th>
|
||||
<th>Tier 2</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Viewing</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RSS</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API</td>
|
||||
<td>❌</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Patron List</td>
|
||||
<td>❌</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Uploads</td>
|
||||
<td>❌</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Content Adding</td>
|
||||
<td>❌</td>
|
||||
<td>✅</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sponsored Link</td>
|
||||
<td>❌</td>
|
||||
<td>❌</td>
|
||||
<td>✅</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="hero mb-5">
|
||||
<div class="hero-body">
|
||||
<p class="title">Thank you for your support!</p>
|
||||
<p class="subtitle is-6">
|
||||
Change your patron tier at
|
||||
<.external_link target="_blank" href="https://patreon.com/CJ_Clippy">
|
||||
patreon.com/CJ_Clippy
|
||||
</.external_link>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
"""
|
||||
end
|
||||
|
||||
|
@ -6,7 +6,9 @@ defmodule BrightWeb.Router do
|
||||
import BrightWeb.AuthController,
|
||||
only: [
|
||||
fetch_current_user: 2,
|
||||
require_admin_user: 2
|
||||
require_admin_user: 2,
|
||||
require_authenticated_user: 2,
|
||||
require_patron_tier_1: 2
|
||||
]
|
||||
|
||||
pipeline :browser do
|
||||
@ -36,7 +38,14 @@ defmodule BrightWeb.Router do
|
||||
post("/:provider/callback", AuthController, :callback)
|
||||
end
|
||||
|
||||
## protected routes
|
||||
## tier 1 protected routes
|
||||
scope "/", BrightWeb do
|
||||
pipe_through [:browser, :require_authenticated_user, :require_patron_tier_1]
|
||||
|
||||
resources("/vtubers", VtuberController, only: [:new, :create, :edit, :update])
|
||||
end
|
||||
|
||||
## admin protected routes
|
||||
## this section needs to be above the unprotected routes,
|
||||
## so routes like "/streams/new" take precedence.
|
||||
scope "/", BrightWeb do
|
||||
@ -67,31 +76,24 @@ defmodule BrightWeb.Router do
|
||||
# end
|
||||
|
||||
resources("/vods", VodController, only: [:create, :new, :edit, :update, :delete])
|
||||
resources("/vtubers", VtuberController, only: [:create, :new, :edit, :update, :delete])
|
||||
resources("/vtubers", VtuberController, only: [:delete])
|
||||
|
||||
get("/tags/new", TagController, :new)
|
||||
post("/tags", TagController, :create)
|
||||
get("/tags/:id/edit", TagController, :edit)
|
||||
resources("/tags", TagController, only: [:new, :create, :edit, :update, :delete])
|
||||
|
||||
resources("/torrents", TorrentController, only: [:create, :new, :edit, :update, :delete])
|
||||
resources("/torrents", TorrentController, only: [:new, :create, :edit, :update, :delete])
|
||||
|
||||
## !!! DANGER, platforms must only be writable by admins, (unless we implement SVG sanitizing)
|
||||
## @todo remove SVGs from the database and instead put them in assets
|
||||
resources("/platforms", PlatformController, only: [:new, :create, :edit, :update, :delete])
|
||||
|
||||
oban_dashboard("/oban")
|
||||
|
||||
live_session :authenticated,
|
||||
on_mount: [{BrightWeb.AuthController, :ensure_authenticated}] do
|
||||
live("/profile", ProfileLive)
|
||||
end
|
||||
end
|
||||
|
||||
## tier 0 users can access these routes
|
||||
scope "/", BrightWeb do
|
||||
pipe_through(:browser)
|
||||
|
||||
get("/", PageController, :home)
|
||||
|
||||
get("/patrons", PatronController, :index)
|
||||
get("/about", PageController, :about)
|
||||
get("/goals", PageController, :about)
|
||||
@ -105,8 +107,7 @@ defmodule BrightWeb.Router do
|
||||
get("/vods/:id", VodController, :show)
|
||||
get("/vods", VodController, :index)
|
||||
|
||||
get("/tags", TagController, :index)
|
||||
get("/tags/:id", TagController, :show)
|
||||
resources("/tags", TagController, only: [:index, :show])
|
||||
|
||||
get("/platforms", PlatformController, :index)
|
||||
get("/platforms/:id", PlatformController, :show)
|
||||
@ -117,6 +118,11 @@ defmodule BrightWeb.Router do
|
||||
get("/vods", VodController, :index)
|
||||
get("/vods/:id", VodController, :show)
|
||||
end
|
||||
|
||||
live_session :authenticated,
|
||||
on_mount: [{BrightWeb.AuthController, :ensure_authenticated}] do
|
||||
live("/profile", ProfileLive)
|
||||
end
|
||||
end
|
||||
|
||||
scope "/feeds", BrightWeb do
|
||||
|
@ -1,8 +1,16 @@
|
||||
defmodule Bright.PatreonEntitlementsTest do
|
||||
use ExUnit.Case
|
||||
alias Bright.PatreonEntitlements
|
||||
alias Bright.Patrons.PatreonEntitlements
|
||||
|
||||
describe "extract_tiers/1" do
|
||||
test "handles empty included list" do
|
||||
assert PatreonEntitlements.extract_tiers(%{"included" => []}) == []
|
||||
end
|
||||
|
||||
test "handles no included list" do
|
||||
assert PatreonEntitlements.extract_tiers(%{"data" => []}) == []
|
||||
end
|
||||
|
||||
test "returns a list of tier IDs when included contains tier items" do
|
||||
response_body = %{
|
||||
"included" => [
|
||||
|
@ -1,64 +1,80 @@
|
||||
defmodule Bright.TierMapperTest do
|
||||
use ExUnit.Case
|
||||
alias Bright.TierMapper
|
||||
alias Bright.Patrons.TierMapper
|
||||
|
||||
describe "largest_tier_for_platform/2" do
|
||||
test "gets the big big" do
|
||||
assert TierMapper.largest_tier_for_platform("patreon", ["10620388", "8154170"]) == 1
|
||||
assert TierMapper.largest_tier_for_platform("patreon", ["10620388", "8154170"]) === 1
|
||||
end
|
||||
|
||||
test "handles nil list" do
|
||||
assert TierMapper.largest_tier_for_platform("patreon", nil) === 0
|
||||
end
|
||||
|
||||
test "handles platform with empty list" do
|
||||
assert TierMapper.largest_tier_for_platform("patreon", []) === 0
|
||||
end
|
||||
|
||||
test "handles nil platform" do
|
||||
assert TierMapper.largest_tier_for_platform(nil) === 0
|
||||
end
|
||||
|
||||
test "handles empty list" do
|
||||
assert TierMapper.largest_tier_for_platform([]) === 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_tier_number/2" do
|
||||
test "maps Patreon 'everyone' tier to 0" do
|
||||
assert TierMapper.get_tier_number("patreon", "-1") == 0
|
||||
assert TierMapper.get_tier_number("patreon", "-1") === 0
|
||||
end
|
||||
|
||||
test "maps Patreon 'free' tier to 0" do
|
||||
assert TierMapper.get_tier_number("patreon", "10620388") == 0
|
||||
assert TierMapper.get_tier_number("patreon", "10620388") === 0
|
||||
end
|
||||
|
||||
test "maps Patreon 'archiveSupporter' tier to 1" do
|
||||
assert TierMapper.get_tier_number("patreon", "8154170") == 1
|
||||
assert TierMapper.get_tier_number("patreon", "8154170") === 1
|
||||
end
|
||||
|
||||
test "maps Patreon 'stealthSupporter' tier to 1" do
|
||||
assert TierMapper.get_tier_number("patreon", "9561793") == 1
|
||||
assert TierMapper.get_tier_number("patreon", "9561793") === 1
|
||||
end
|
||||
|
||||
test "maps Patreon 'tuneItUp' tier to 2" do
|
||||
assert TierMapper.get_tier_number("patreon", "9184994") == 2
|
||||
assert TierMapper.get_tier_number("patreon", "9184994") === 2
|
||||
end
|
||||
|
||||
test "maps Patreon 'maxQ' tier to 2" do
|
||||
assert TierMapper.get_tier_number("patreon", "22529959") == 2
|
||||
assert TierMapper.get_tier_number("patreon", "22529959") === 2
|
||||
end
|
||||
|
||||
test "maps Patreon 'archiveCollector' tier to 3" do
|
||||
assert TierMapper.get_tier_number("patreon", "8154171") == 3
|
||||
assert TierMapper.get_tier_number("patreon", "8154171") === 3
|
||||
end
|
||||
|
||||
test "maps Patreon 'advancedArchiveSupporter' tier to 3" do
|
||||
assert TierMapper.get_tier_number("patreon", "8686045") == 3
|
||||
assert TierMapper.get_tier_number("patreon", "8686045") === 3
|
||||
end
|
||||
|
||||
test "maps Patreon 'quantumSupporter' tier to 4" do
|
||||
assert TierMapper.get_tier_number("patreon", "8694826") == 4
|
||||
assert TierMapper.get_tier_number("patreon", "8694826") === 4
|
||||
end
|
||||
|
||||
test "maps Patreon 'sneakyQuantumSupporter' tier to 4" do
|
||||
assert TierMapper.get_tier_number("patreon", "9560538") == 4
|
||||
assert TierMapper.get_tier_number("patreon", "9560538") === 4
|
||||
end
|
||||
|
||||
test "maps Patreon 'luberPlusPlus' tier to 5" do
|
||||
assert TierMapper.get_tier_number("patreon", "8686022") == 5
|
||||
assert TierMapper.get_tier_number("patreon", "8686022") === 5
|
||||
end
|
||||
|
||||
test "returns 0 for unknown Patreon tier" do
|
||||
assert TierMapper.get_tier_number("patreon", "99999999") == 0
|
||||
assert TierMapper.get_tier_number("patreon", "99999999") === 0
|
||||
end
|
||||
|
||||
test "returns 0 for non-Patreon platforms" do
|
||||
assert TierMapper.get_tier_number("someotherplatform", "10620388") == 0
|
||||
assert TierMapper.get_tier_number("someotherplatform", "10620388") === 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,46 +1,193 @@
|
||||
defmodule BrightWeb.AuthControllerTest do
|
||||
use BrightWeb.ConnCase
|
||||
alias Bright.Users
|
||||
alias BrightWeb.AuthController
|
||||
require Logger
|
||||
|
||||
@patron_tier_1_required_error "This route is for tier 1 or higher."
|
||||
@patron_tier_2_required_error "This route is for tier 2 or higher."
|
||||
@patron_tier_3_required_error "This route is for tier 3 or higher."
|
||||
|
||||
describe "patreon auth" do
|
||||
test "successful auth on existing user signs you in", %{conn: conn} do
|
||||
test "successful auth on existing user sets the session", %{conn: conn} do
|
||||
Logger.debug("successful auth on existing user sets the session")
|
||||
user = Bright.Repo.insert!(%Bright.Users.User{patreon_id: 1234})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:ueberauth_auth, %{provider: :patreon, info: %{nickname: "joeblow"}})
|
||||
|> assign(:ueberauth_auth, %{
|
||||
provider: :patreon,
|
||||
info: %{nickname: "joeblow"},
|
||||
uid: 1234,
|
||||
extra: %{raw_info: %{user: %{}}}
|
||||
})
|
||||
|> get("/auth/patreon/callback")
|
||||
|
||||
assert redirected_to(conn) == Routes.home_path(conn, :show)
|
||||
assert get_session(conn, "id") == user.id
|
||||
end
|
||||
|
||||
test "successful auth on new user sends you to profile", %{conn: conn} do
|
||||
Logger.debug("successful auth on new user sends you to profile")
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:ueberauth_auth, %{
|
||||
provider: :patreon,
|
||||
info: %{name: "Joe Blow", handle: "joeblow"},
|
||||
uid: 1234
|
||||
uid: 4321,
|
||||
extra: %{raw_info: %{user: %{}}}
|
||||
})
|
||||
|> get("/auth/patreon/callback")
|
||||
|
||||
assert redirected_to(conn) ==
|
||||
Routes.user_path(conn, :profile, %{
|
||||
name: "Joe Blow",
|
||||
handle: "joeblow",
|
||||
patreon_handle: "joeblow"
|
||||
})
|
||||
assert redirected_to(conn) == ~p"/profile"
|
||||
end
|
||||
|
||||
test "failed auth doesn't sign you in", %{conn: conn} do
|
||||
test "failed auth doesn't set the session", %{conn: conn} do
|
||||
Logger.debug("failed auth doesn't put a user id in the session")
|
||||
|
||||
auth = %Ueberauth.Failure{
|
||||
errors: [%Ueberauth.Failure.Error{message: "simulated failure"}],
|
||||
provider: :patreon,
|
||||
strategy: Ueberauth.Strategy.Patreon
|
||||
}
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> assign(:ueberauth_failure, %{})
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> assign(:ueberauth_failure, auth)
|
||||
|> get("/auth/patreon/callback")
|
||||
|> BrightWeb.AuthController.callback(%{})
|
||||
|
||||
assert conn.status == 302
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) =~ "simulated failure"
|
||||
assert get_session(conn, :id) == nil
|
||||
end
|
||||
|
||||
test "user stays logged in even if they reload the page", %{conn: conn} do
|
||||
Logger.debug("user stays logged in even if they reload the page")
|
||||
|
||||
user = Bright.Repo.insert!(%Bright.Users.User{patreon_id: 1234})
|
||||
|
||||
# Simulate login
|
||||
conn =
|
||||
conn
|
||||
|> assign(:ueberauth_auth, %{
|
||||
provider: :patreon,
|
||||
info: %{nickname: "joeblow"},
|
||||
uid: 1234,
|
||||
extra: %{raw_info: %{user: %{}}}
|
||||
})
|
||||
|> get("/auth/patreon/callback")
|
||||
|
||||
assert conn.status == 200
|
||||
assert get_session(conn, "id") == nil
|
||||
# Verify user is logged in
|
||||
assert get_session(conn, "id") == user.id
|
||||
|
||||
# Simulate a page reload (new GET request)
|
||||
conn = get(conn, "/profile")
|
||||
|
||||
# Verify the session is still active
|
||||
assert get_session(conn, "id") == user.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "require_patron_tier/2" do
|
||||
test "allows access to admins", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> get("/")
|
||||
|> assign(:current_user, %{patron_tier: 0, role: "admin"})
|
||||
|> AuthController.require_patron_tier(3)
|
||||
|
||||
refute conn.halted
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
|
||||
end
|
||||
|
||||
test "allows access when patron tier is higher than required", %{conn: conn} do
|
||||
# Setup conn with a user that has higher patron tier
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> get("/")
|
||||
|> assign(:current_user, %{patron_tier: 3})
|
||||
# Call the plug with a lower tier requirement
|
||||
|> AuthController.require_patron_tier(2)
|
||||
|
||||
# Assert the connection wasn't halted or redirected
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
test "allows access when patron tier equals required tier", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> assign(:current_user, %{patron_tier: 2})
|
||||
|> AuthController.require_patron_tier(2)
|
||||
|
||||
refute conn.halted
|
||||
end
|
||||
|
||||
test "redirects when patron tier is lower than required", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> assign(:current_user, %{patron_tier: 1})
|
||||
|> get("/")
|
||||
|> AuthController.require_patron_tier(2)
|
||||
|
||||
assert conn.halted
|
||||
assert redirected_to(conn) == "/"
|
||||
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
|
||||
"This route is for tier 2 or higher."
|
||||
end
|
||||
|
||||
test "redirects when user has no patron tier", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> assign(:current_user, %{})
|
||||
|> get("/")
|
||||
|> AuthController.require_patron_tier(2)
|
||||
|
||||
assert conn.halted
|
||||
assert redirected_to(conn) == "/"
|
||||
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
|
||||
"This route is for tier 2 or higher."
|
||||
end
|
||||
|
||||
@tag :unit
|
||||
test "redirects when no current user exists", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> assign(:current_user, %{})
|
||||
|> get("/")
|
||||
|> AuthController.require_patron_tier(2)
|
||||
|
||||
assert conn.halted
|
||||
assert redirected_to(conn) == "/"
|
||||
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
|
||||
"This route is for tier 2 or higher."
|
||||
end
|
||||
|
||||
@tag :unit
|
||||
test "respects custom return path", %{conn: conn} do
|
||||
conn =
|
||||
conn
|
||||
|> bypass_through(BrightWeb.Router, :browser)
|
||||
|> assign(:current_user, %{patron_tier: 1})
|
||||
|> assign(:user_return_to, "/custom/path")
|
||||
|> get("/")
|
||||
|> AuthController.require_patron_tier(2)
|
||||
|
||||
assert conn.halted
|
||||
assert redirected_to(conn) == "/custom/path"
|
||||
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) ==
|
||||
"This route is for tier 2 or higher."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -3,6 +3,6 @@ defmodule BrightWeb.PageControllerTest do
|
||||
|
||||
test "GET /", %{conn: conn} do
|
||||
conn = get(conn, ~p"/")
|
||||
assert html_response(conn, 200) =~ "Futureporn.net"
|
||||
assert html_response(conn, 202) =~ "Futureporn.net"
|
||||
end
|
||||
end
|
||||
|
@ -15,6 +15,8 @@ defmodule BrightWeb.PlatformControllerTest do
|
||||
end
|
||||
|
||||
describe "new platform" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, ~p"/platforms/new")
|
||||
assert html_response(conn, 200) =~ "New Platform"
|
||||
@ -22,6 +24,8 @@ defmodule BrightWeb.PlatformControllerTest do
|
||||
end
|
||||
|
||||
describe "create platform" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/platforms", platform: @create_attrs)
|
||||
|
||||
@ -39,7 +43,7 @@ defmodule BrightWeb.PlatformControllerTest do
|
||||
end
|
||||
|
||||
describe "edit platform" do
|
||||
setup [:create_platform]
|
||||
setup [:create_platform, :create_admin]
|
||||
|
||||
test "renders form for editing chosen platform", %{conn: conn, platform: platform} do
|
||||
conn = get(conn, ~p"/platforms/#{platform}/edit")
|
||||
@ -48,7 +52,7 @@ defmodule BrightWeb.PlatformControllerTest do
|
||||
end
|
||||
|
||||
describe "update platform" do
|
||||
setup [:create_platform]
|
||||
setup [:create_platform, :create_admin]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, platform: platform} do
|
||||
conn = put(conn, ~p"/platforms/#{platform}", platform: @update_attrs)
|
||||
@ -65,7 +69,7 @@ defmodule BrightWeb.PlatformControllerTest do
|
||||
end
|
||||
|
||||
describe "delete platform" do
|
||||
setup [:create_platform]
|
||||
setup [:create_platform, :create_admin]
|
||||
|
||||
test "deletes chosen platform", %{conn: conn, platform: platform} do
|
||||
conn = delete(conn, ~p"/platforms/#{platform}")
|
||||
|
@ -2,6 +2,7 @@ defmodule BrightWeb.StreamControllerTest do
|
||||
use BrightWeb.ConnCase
|
||||
|
||||
import Bright.StreamsFixtures
|
||||
require Logger
|
||||
|
||||
@create_attrs %{date: ~U[2024-12-28 03:31:00Z], title: "some title", notes: "some notes"}
|
||||
@update_attrs %{
|
||||
@ -19,13 +20,17 @@ defmodule BrightWeb.StreamControllerTest do
|
||||
end
|
||||
|
||||
describe "new stream" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, ~p"/streams/new")
|
||||
assert html_response(conn, 200) =~ "New Stream"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create stream" do
|
||||
describe "admin create stream" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/streams", stream: @create_attrs)
|
||||
|
||||
@ -38,12 +43,13 @@ defmodule BrightWeb.StreamControllerTest do
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/streams", stream: @invalid_attrs)
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
|
||||
assert html_response(conn, 200) =~ "New Stream"
|
||||
end
|
||||
end
|
||||
|
||||
describe "edit stream" do
|
||||
setup [:create_stream]
|
||||
setup [:create_stream, :create_admin]
|
||||
|
||||
test "renders form for editing chosen stream", %{conn: conn, stream: stream} do
|
||||
conn = get(conn, ~p"/streams/#{stream}/edit")
|
||||
@ -51,8 +57,8 @@ defmodule BrightWeb.StreamControllerTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "update stream" do
|
||||
setup [:create_stream]
|
||||
describe "admin update stream" do
|
||||
setup [:create_stream, :create_admin]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, stream: stream} do
|
||||
conn = put(conn, ~p"/streams/#{stream}", stream: @update_attrs)
|
||||
@ -64,12 +70,13 @@ defmodule BrightWeb.StreamControllerTest do
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, stream: stream} do
|
||||
conn = put(conn, ~p"/streams/#{stream}", stream: @invalid_attrs)
|
||||
Logger.debug("renders errors when data is invalid. conn=#{inspect(conn)}")
|
||||
assert html_response(conn, 200) =~ "Edit Stream"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete stream" do
|
||||
setup [:create_stream]
|
||||
describe "admin delete stream" do
|
||||
setup [:create_stream, :create_admin]
|
||||
|
||||
test "deletes chosen stream", %{conn: conn, stream: stream} do
|
||||
conn = delete(conn, ~p"/streams/#{stream}")
|
||||
|
@ -2,10 +2,11 @@ defmodule BrightWeb.TagControllerTest do
|
||||
use BrightWeb.ConnCase
|
||||
|
||||
import Bright.TagsFixtures
|
||||
require Logger
|
||||
|
||||
@create_attrs %{name: "some name"}
|
||||
@update_attrs %{name: "some updated name"}
|
||||
@invalid_attrs %{name: nil}
|
||||
@invalid_attrs %{name: 3}
|
||||
|
||||
describe "index" do
|
||||
test "lists all tags", %{conn: conn} do
|
||||
@ -15,6 +16,8 @@ defmodule BrightWeb.TagControllerTest do
|
||||
end
|
||||
|
||||
describe "new tag" do
|
||||
setup :create_admin
|
||||
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, ~p"/tags/new")
|
||||
assert html_response(conn, 200) =~ "New Tag"
|
||||
@ -22,6 +25,8 @@ defmodule BrightWeb.TagControllerTest do
|
||||
end
|
||||
|
||||
describe "create tag" do
|
||||
setup :create_admin
|
||||
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/tags", tag: @create_attrs)
|
||||
|
||||
@ -39,7 +44,7 @@ defmodule BrightWeb.TagControllerTest do
|
||||
end
|
||||
|
||||
describe "edit tag" do
|
||||
setup [:create_tag]
|
||||
setup [:create_tag, :create_admin]
|
||||
|
||||
test "renders form for editing chosen tag", %{conn: conn, tag: tag} do
|
||||
conn = get(conn, ~p"/tags/#{tag}/edit")
|
||||
@ -48,10 +53,11 @@ defmodule BrightWeb.TagControllerTest do
|
||||
end
|
||||
|
||||
describe "update tag" do
|
||||
setup [:create_tag]
|
||||
setup [:create_tag, :create_admin]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, tag: tag} do
|
||||
conn = put(conn, ~p"/tags/#{tag}", tag: @update_attrs)
|
||||
Logger.debug("tag update redirect conn=#{inspect(conn)}")
|
||||
assert redirected_to(conn) == ~p"/tags/#{tag}"
|
||||
|
||||
conn = get(conn, ~p"/tags/#{tag}")
|
||||
@ -65,7 +71,7 @@ defmodule BrightWeb.TagControllerTest do
|
||||
end
|
||||
|
||||
describe "delete tag" do
|
||||
setup [:create_tag]
|
||||
setup [:create_tag, :create_admin]
|
||||
|
||||
test "deletes chosen tag", %{conn: conn, tag: tag} do
|
||||
conn = delete(conn, ~p"/tags/#{tag}")
|
||||
|
@ -19,12 +19,14 @@ defmodule BrightWeb.TorrentControllerTest do
|
||||
|
||||
describe "index" do
|
||||
test "lists all torrent", %{conn: conn} do
|
||||
conn = get(conn, ~p"/torrent")
|
||||
conn = get(conn, ~p"/torrents")
|
||||
assert html_response(conn, 200) =~ "Listing Torrent"
|
||||
end
|
||||
end
|
||||
|
||||
describe "new torrent" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, ~p"/torrents/new")
|
||||
assert html_response(conn, 200) =~ "New Torrent"
|
||||
@ -32,8 +34,10 @@ defmodule BrightWeb.TorrentControllerTest do
|
||||
end
|
||||
|
||||
describe "create torrent" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/torrent", torrent: @create_attrs)
|
||||
conn = post(conn, ~p"/torrents", torrent: @create_attrs)
|
||||
|
||||
assert %{id: id} = redirected_params(conn)
|
||||
assert redirected_to(conn) == ~p"/torrents/#{id}"
|
||||
@ -49,7 +53,7 @@ defmodule BrightWeb.TorrentControllerTest do
|
||||
end
|
||||
|
||||
describe "edit torrent" do
|
||||
setup [:create_torrent]
|
||||
setup [:create_torrent, :create_admin]
|
||||
|
||||
test "renders form for editing chosen torrent", %{conn: conn, torrent: torrent} do
|
||||
conn = get(conn, ~p"/torrents/#{torrent}/edit")
|
||||
@ -58,7 +62,7 @@ defmodule BrightWeb.TorrentControllerTest do
|
||||
end
|
||||
|
||||
describe "update torrent" do
|
||||
setup [:create_torrent]
|
||||
setup [:create_torrent, :create_admin]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, torrent: torrent} do
|
||||
conn = put(conn, ~p"/torrents/#{torrent}", torrent: @update_attrs)
|
||||
@ -75,11 +79,11 @@ defmodule BrightWeb.TorrentControllerTest do
|
||||
end
|
||||
|
||||
describe "delete torrent" do
|
||||
setup [:create_torrent]
|
||||
setup [:create_torrent, :create_admin]
|
||||
|
||||
test "deletes chosen torrent", %{conn: conn, torrent: torrent} do
|
||||
conn = delete(conn, ~p"/torrents/#{torrent}")
|
||||
assert redirected_to(conn) == ~p"/torrent"
|
||||
assert redirected_to(conn) == ~p"/torrents"
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, ~p"/torrents/#{torrent}")
|
||||
|
@ -1,88 +0,0 @@
|
||||
defmodule BrightWeb.UrlControllerTest do
|
||||
use BrightWeb.ConnCase
|
||||
|
||||
import Bright.UrlsFixtures
|
||||
|
||||
alias Bright.Urls.Url
|
||||
|
||||
@create_attrs %{
|
||||
link: "some link",
|
||||
title: "some title"
|
||||
}
|
||||
@update_attrs %{
|
||||
link: "some updated link",
|
||||
title: "some updated title"
|
||||
}
|
||||
@invalid_attrs %{link: nil, title: nil}
|
||||
|
||||
setup %{conn: conn} do
|
||||
{:ok, conn: put_req_header(conn, "accept", "application/json")}
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
test "lists all urls", %{conn: conn} do
|
||||
conn = get(conn, ~p"/api/urls")
|
||||
assert json_response(conn, 200)["data"] == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "create url" do
|
||||
test "renders url when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/api/urls", url: @create_attrs)
|
||||
assert %{"id" => id} = json_response(conn, 201)["data"]
|
||||
|
||||
conn = get(conn, ~p"/api/urls/#{id}")
|
||||
|
||||
assert %{
|
||||
"id" => ^id,
|
||||
"link" => "some link",
|
||||
"title" => "some title"
|
||||
} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/api/urls", url: @invalid_attrs)
|
||||
assert json_response(conn, 422)["errors"] != %{}
|
||||
end
|
||||
end
|
||||
|
||||
describe "update url" do
|
||||
setup [:create_url]
|
||||
|
||||
test "renders url when data is valid", %{conn: conn, url: %Url{id: id} = url} do
|
||||
conn = put(conn, ~p"/api/urls/#{url}", url: @update_attrs)
|
||||
assert %{"id" => ^id} = json_response(conn, 200)["data"]
|
||||
|
||||
conn = get(conn, ~p"/api/urls/#{id}")
|
||||
|
||||
assert %{
|
||||
"id" => ^id,
|
||||
"link" => "some updated link",
|
||||
"title" => "some updated title"
|
||||
} = json_response(conn, 200)["data"]
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, url: url} do
|
||||
conn = put(conn, ~p"/api/urls/#{url}", url: @invalid_attrs)
|
||||
assert json_response(conn, 422)["errors"] != %{}
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete url" do
|
||||
setup [:create_url]
|
||||
|
||||
test "deletes chosen url", %{conn: conn, url: url} do
|
||||
conn = delete(conn, ~p"/api/urls/#{url}")
|
||||
assert response(conn, 204)
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, ~p"/api/urls/#{url}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp create_url(_) do
|
||||
url = url_fixture()
|
||||
%{url: url}
|
||||
end
|
||||
end
|
@ -2,14 +2,13 @@ defmodule BrightWeb.VodControllerTest do
|
||||
use BrightWeb.ConnCase
|
||||
|
||||
import Bright.StreamsFixtures
|
||||
require Logger
|
||||
|
||||
@create_attrs %{
|
||||
s3_cdn_url: "some s3_cdn_url",
|
||||
s3_upload_id: "some s3_upload_id",
|
||||
s3_key: "some s3_key",
|
||||
s3_bucket: "some s3_bucket",
|
||||
mux_asset_id: "some mux_asset_id",
|
||||
mux_playback_id: "some mux_playback_id",
|
||||
torrent: "some torrent"
|
||||
}
|
||||
@update_attrs %{
|
||||
@ -22,6 +21,7 @@ defmodule BrightWeb.VodControllerTest do
|
||||
torrent: "some updated torrent"
|
||||
}
|
||||
@invalid_attrs %{
|
||||
stream_id: "this is obviously invalid",
|
||||
s3_cdn_url: nil,
|
||||
s3_upload_id: nil,
|
||||
s3_key: nil,
|
||||
@ -39,6 +39,8 @@ defmodule BrightWeb.VodControllerTest do
|
||||
end
|
||||
|
||||
describe "new vod" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "renders form", %{conn: conn} do
|
||||
conn = get(conn, ~p"/vods/new")
|
||||
assert html_response(conn, 200) =~ "New Vod"
|
||||
@ -46,8 +48,12 @@ defmodule BrightWeb.VodControllerTest do
|
||||
end
|
||||
|
||||
describe "create vod" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "redirects to show when data is valid", %{conn: conn} do
|
||||
conn = post(conn, ~p"/vods", vod: @create_attrs)
|
||||
stream = stream_fixture()
|
||||
conn = post(conn, ~p"/vods", vod: Map.put(@create_attrs, :stream_id, stream.id))
|
||||
Logger.debug(">>> redirect conn=#{inspect(conn)}")
|
||||
|
||||
assert %{id: id} = redirected_params(conn)
|
||||
assert redirected_to(conn) == ~p"/vods/#{id}"
|
||||
@ -63,7 +69,7 @@ defmodule BrightWeb.VodControllerTest do
|
||||
end
|
||||
|
||||
describe "edit vod" do
|
||||
setup [:create_vod]
|
||||
setup [:create_vod, :create_admin]
|
||||
|
||||
test "renders form for editing chosen vod", %{conn: conn, vod: vod} do
|
||||
conn = get(conn, ~p"/vods/#{vod}/edit")
|
||||
@ -72,7 +78,7 @@ defmodule BrightWeb.VodControllerTest do
|
||||
end
|
||||
|
||||
describe "update vod" do
|
||||
setup [:create_vod]
|
||||
setup [:create_vod, :create_admin]
|
||||
|
||||
test "redirects when data is valid", %{conn: conn, vod: vod} do
|
||||
conn = put(conn, ~p"/vods/#{vod}", vod: @update_attrs)
|
||||
@ -84,12 +90,21 @@ defmodule BrightWeb.VodControllerTest do
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, vod: vod} do
|
||||
conn = put(conn, ~p"/vods/#{vod}", vod: @invalid_attrs)
|
||||
|
||||
Logger.debug("renders errors... conn=#{inspect(conn)}")
|
||||
|
||||
assert html_response(conn, 200) =~ "Edit Vod"
|
||||
|
||||
assert conn.assigns.changeset.valid? == false
|
||||
# kinda weird that there's no flash error for this
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
|
||||
# kinda weird that Phoenix gives this a 200 rather than 401
|
||||
assert html_response(conn, 200) =~ "is invalid"
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete vod" do
|
||||
setup [:create_vod]
|
||||
setup [:create_vod, :create_admin]
|
||||
|
||||
test "deletes chosen vod", %{conn: conn, vod: vod} do
|
||||
conn = delete(conn, ~p"/vods/#{vod}")
|
||||
@ -102,7 +117,8 @@ defmodule BrightWeb.VodControllerTest do
|
||||
end
|
||||
|
||||
defp create_vod(_) do
|
||||
vod = vod_fixture()
|
||||
stream = stream_fixture()
|
||||
vod = vod_fixture(%{stream_id: stream.id})
|
||||
%{vod: vod}
|
||||
end
|
||||
end
|
||||
|
@ -7,10 +7,18 @@ defmodule BrightWeb.VtuberControllerTest do
|
||||
import Bright.VtubersFixtures
|
||||
require Logger
|
||||
|
||||
@create_attrs %{}
|
||||
@create_attrs %{
|
||||
slug: "testvtuber",
|
||||
display_name: "test",
|
||||
theme_color: "#813d9c",
|
||||
image: "https://example.com/image.jpg"
|
||||
}
|
||||
@update_attrs %{}
|
||||
@invalid_attrs %{}
|
||||
@invalid_attrs %{theme_color: 3}
|
||||
@only_admins_error "Only admins can do that."
|
||||
@patron_tier_1_required_error "This route is for tier 1 or higher."
|
||||
@patron_tier_2_required_error "This route is for tier 2 or higher."
|
||||
@patron_tier_3_required_error "This route is for tier 3 or higher."
|
||||
|
||||
describe "index" do
|
||||
test "lists all vtubers", %{conn: conn} do
|
||||
@ -34,12 +42,12 @@ defmodule BrightWeb.VtuberControllerTest do
|
||||
test "redirects to /vtubers", %{conn: conn} do
|
||||
conn = get(conn, ~p"/vtubers/new")
|
||||
assert html_response(conn, 302) =~ "<html>"
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @only_admins_error
|
||||
assert redirected_to(conn) == ~p"/vtubers"
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
|
||||
assert redirected_to(conn) == ~p"/"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create vtuber" do
|
||||
describe "create vtuber as admin" do
|
||||
setup [:create_admin]
|
||||
|
||||
test "redirects to :show when data is valid", %{conn: conn} do
|
||||
@ -47,11 +55,12 @@ defmodule BrightWeb.VtuberControllerTest do
|
||||
|
||||
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
|
||||
|
||||
assert %{id: id} = redirected_params(conn)
|
||||
assert redirected_to(conn) == ~p"/vtubers/#{id}"
|
||||
Logger.debug("CREATED conn=#{inspect(conn)}")
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "created successfully."
|
||||
|
||||
conn = get(conn, ~p"/vtubers/#{id}")
|
||||
assert html_response(conn, 200) =~ "Vtuber #{id}"
|
||||
assert %{id: id} = redirected_params(conn, 302)
|
||||
assert redirected_to(conn) == ~p"/vtubers/#{id}"
|
||||
end
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, user: user} do
|
||||
@ -60,6 +69,73 @@ defmodule BrightWeb.VtuberControllerTest do
|
||||
end
|
||||
end
|
||||
|
||||
@tag :onlyme
|
||||
describe "create vtuber as tier 0" do
|
||||
setup [:create_patron_tier_0_user]
|
||||
|
||||
test "user with patron_tier 0 cannot :new", %{conn: conn} do
|
||||
conn = get(conn, ~p"/vtubers/new")
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) == ~p"/"
|
||||
end
|
||||
|
||||
test "user with patron_tier 0 cannot :create", %{conn: conn} do
|
||||
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
|
||||
assert conn.status == 302
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
|
||||
assert redirected_to(conn) == ~p"/"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create vtuber as tier 1" do
|
||||
setup [:create_patron_tier_1_user]
|
||||
|
||||
test "authorized to :new", %{conn: conn} do
|
||||
conn = get(conn, ~p"/vtubers/new")
|
||||
assert conn.status == 200
|
||||
end
|
||||
|
||||
test "authorized to :create", %{conn: conn} do
|
||||
Logger.debug("conn=#{inspect(conn)}")
|
||||
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "success"
|
||||
assert conn.status == 302
|
||||
assert redirected_to(conn) =~ "/vtubers/"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create vtuber as tier 2" do
|
||||
setup [:create_patron_tier_2_user]
|
||||
|
||||
test "user with patron_tier 2 can :new", %{conn: conn} do
|
||||
conn = get(conn, ~p"/vtubers/new")
|
||||
assert conn.status == 200
|
||||
end
|
||||
|
||||
test "user with patron_tier 2 can :create", %{conn: conn} do
|
||||
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
|
||||
assert conn.status == 302
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "success"
|
||||
end
|
||||
end
|
||||
|
||||
describe "create vtuber as tier 3" do
|
||||
setup [:create_patron_tier_3_user]
|
||||
|
||||
test "user with patron_tier 3 can :new", %{conn: conn} do
|
||||
conn = get(conn, ~p"/vtubers/new")
|
||||
assert conn.status == 200
|
||||
end
|
||||
|
||||
test "user with patron_tier 3 can :create", %{conn: conn} do
|
||||
conn = post(conn, ~p"/vtubers", vtuber: @create_attrs)
|
||||
assert conn.status == 302
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "created"
|
||||
end
|
||||
end
|
||||
|
||||
@tag :onlyme
|
||||
describe "edit vtuber as admin" do
|
||||
setup [:create_vtuber, :create_admin]
|
||||
|
||||
@ -95,22 +171,35 @@ defmodule BrightWeb.VtuberControllerTest do
|
||||
|
||||
test "renders errors when data is invalid", %{conn: conn, vtuber: vtuber} do
|
||||
conn = put(conn, ~p"/vtubers/#{vtuber}", vtuber: @invalid_attrs)
|
||||
assert html_response(conn, 200) =~ "Edit Vtuber"
|
||||
Logger.debug(">>> conn=#{inspect(conn)}")
|
||||
assert conn.assigns.changeset.valid? == false
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == nil
|
||||
# kinda weird that Phoenix gives this a 200 rather than 401
|
||||
assert html_response(conn, 200) =~ "is invalid"
|
||||
end
|
||||
end
|
||||
|
||||
describe "update vtuber as user" do
|
||||
describe "update vtuber as user (patron_tier 0)" do
|
||||
setup [:create_vtuber, :create_user]
|
||||
|
||||
test "redirects when user is not an admin", %{conn: conn, user: user, vtuber: vtuber} do
|
||||
# test "redirects when data is valid", %{conn: conn, user: user, vtuber: vtuber} do
|
||||
# Logger.debug(">>. redirect conn=#{inspect(conn)}, user=#{inspect(user)}")
|
||||
# conn = put(conn, ~p"/vtubers/#{vtuber}", vtuber: @update_attrs)
|
||||
# assert redirected_to(conn) == ~p"/vtubers/#{vtuber}"
|
||||
|
||||
# conn = get(conn, ~p"/vtubers/#{vtuber}")
|
||||
# assert html_response(conn, 200)
|
||||
# end
|
||||
|
||||
test "redirects", %{conn: conn, user: user, vtuber: vtuber} do
|
||||
Logger.debug("hello here is user=#{inspect(user)}")
|
||||
|
||||
conn = get(conn, ~p"/vtubers/#{vtuber}")
|
||||
conn = put(conn, ~p"/vtubers/#{vtuber}", vtuber: @update_attrs)
|
||||
assert conn.halted
|
||||
|
||||
assert redirected_to(conn) == ~p"/vtubers/#{vtuber}"
|
||||
assert redirected_to(conn) =~ "/"
|
||||
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @only_admins_error
|
||||
assert Phoenix.Flash.get(conn.assigns.flash, :error) == @patron_tier_1_required_error
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -16,6 +16,7 @@ defmodule BrightWeb.ConnCase do
|
||||
"""
|
||||
|
||||
import Bright.UsersFixtures
|
||||
require Logger
|
||||
|
||||
use ExUnit.CaseTemplate
|
||||
|
||||
@ -50,8 +51,32 @@ defmodule BrightWeb.ConnCase do
|
||||
{:ok, user: user, conn: conn}
|
||||
end
|
||||
|
||||
def create_user(%{conn: conn}) do
|
||||
user = user_fixture(%{role: "user", patreon_id: 4321})
|
||||
def create_user(opts) do
|
||||
create_patron_tier_0_user(opts)
|
||||
end
|
||||
|
||||
def create_patron_tier_0_user(%{conn: conn}) do
|
||||
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 0})
|
||||
conn = login_user(conn, user)
|
||||
{:ok, user: user, conn: conn}
|
||||
end
|
||||
|
||||
def create_patron_tier_1_user(%{conn: conn}) do
|
||||
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 1})
|
||||
Logger.debug("user just created. user=#{inspect(user)}")
|
||||
conn = login_user(conn, user)
|
||||
Logger.debug("create_patron_tier_1_user just finished with conn=#{inspect(conn)}")
|
||||
{:ok, user: user, conn: conn}
|
||||
end
|
||||
|
||||
def create_patron_tier_2_user(%{conn: conn}) do
|
||||
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 2})
|
||||
conn = login_user(conn, user)
|
||||
{:ok, user: user, conn: conn}
|
||||
end
|
||||
|
||||
def create_patron_tier_3_user(%{conn: conn}) do
|
||||
user = user_fixture(%{role: "user", patreon_id: 4321, patron_tier: 3})
|
||||
conn = login_user(conn, user)
|
||||
{:ok, user: user, conn: conn}
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user