Skip to content

Commit

Permalink
Merge pull request #69 from oestrich/hosted-site
Browse files Browse the repository at this point in the history
Hosted sites
  • Loading branch information
oestrich committed Mar 24, 2019
2 parents c3ebce2 + 04bf3d1 commit 9f30ab1
Show file tree
Hide file tree
Showing 22 changed files with 353 additions and 57 deletions.
1 change: 1 addition & 0 deletions assets/css/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@import "channels";
@import "forms";
@import "games";
@import "hosted";
@import "home";
@import "panel";
@import "play";
9 changes: 9 additions & 0 deletions assets/css/hosted.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.hosted {
.navbar {
height: 58px;
}

.cover {
margin: auto;
}
}
4 changes: 0 additions & 4 deletions assets/css/overrides.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ pre {
.navbar .navbar-brand {
color: #ffffff;
}
.navbar .navbar-brand:hover,
.navbar .navbar-brand:focus {
color: #000000;
}
.navbar .navbar-text {
color: #ffffff;
}
Expand Down
24 changes: 16 additions & 8 deletions lib/grapevine/cnames.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ defmodule Grapevine.CNAMEs do
end

@doc """
Check if the hostname is known
Look up what type of CNAME the hostname is
"""
def host_known?(host) do
def type_of_host(host) do
case :ets.lookup(@ets_key, host) do
[{^host, _}] ->
true
[{^host, type, game_id}] ->
{:ok, type, game_id}

_ ->
false
{:error, :not_found}
end
end

Expand All @@ -37,13 +37,21 @@ defmodule Grapevine.CNAMEs do
end

def handle_continue(:setup_ets, state) do
Enum.each(Games.with_cname(), fn game ->
:ets.insert(@ets_key, {game.cname, game.id})
end)
Enum.each(Games.with_cname(), &load_game/1)

{:noreply, state}
end

defp load_game(game) do
if game.site_cname do
:ets.insert(@ets_key, {game.site_cname, :site, game.id})
end

if game.client_cname do
:ets.insert(@ets_key, {game.client_cname, :client, game.id})
end
end

def handle_call({:reload}, _from, state) do
{:noreply, state} = handle_continue(:setup_ets, state)
{:reply, :ok, state}
Expand Down
10 changes: 8 additions & 2 deletions lib/grapevine/games.ex
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ defmodule Grapevine.Games do
"""
def with_cname() do
Game
|> where([g], not is_nil(g.cname))
|> where([g], not is_nil(g.client_cname) or not is_nil(g.site_cname))
|> Repo.all()
end

Expand Down Expand Up @@ -178,7 +178,13 @@ defmodule Grapevine.Games do
This value must be set from the database
"""
def get_by_host(host) do
get_by(cname: host, display: true)
case get_by(client_cname: host, display: true) do
{:ok, game} ->
{:ok, game}

{:error, :not_found} ->
get_by(site_cname: host, display: true)
end
end

@doc """
Expand Down
3 changes: 2 additions & 1 deletion lib/grapevine/games/game.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ defmodule Grapevine.Games.Game do
field(:cover_key, Ecto.UUID)
field(:cover_extension, :string)

field(:cname, :string)
field(:site_cname, :string)
field(:client_cname, :string)

belongs_to(:user, User)

Expand Down
11 changes: 11 additions & 0 deletions lib/web/controllers/client/page_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Web.Client.PageController do
use Web, :controller

alias Web.ClientRouter.Helpers, as: Routes

action_fallback(Web.FallbackController)

def index(conn, _params) do
redirect(conn, to: Routes.play_path(conn, :show))
end
end
37 changes: 37 additions & 0 deletions lib/web/controllers/client/play_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule Web.Client.PlayController do
use Web, :controller

alias Grapevine.Games
alias Web.Game

action_fallback(Web.FallbackController)

def show(conn, _params) do
with {:ok, game} <- Games.get_by_host(conn.host),
{:ok, game} <- Games.check_web_client(game),
{:ok, game} <- check_user_allowed(conn, game) do
conn
|> assign(:game, game)
|> assign(:title, "Play #{game.name}")
|> assign(:open_graph_title, game.name)
|> assign(:open_graph_description, "Play #{game.name} on Grapevine")
|> assign(:open_graph_url, play_url(conn, :show, game.short_name))
|> put_layout("cname.html")
|> put_view(Web.PlayView)
|> render("show.html")
else
{:error, _} ->
{:error, :not_found}
end
end

defp check_user_allowed(conn, game) do
case Game.client_allowed?(game, conn.assigns, :current_user) do
true ->
{:ok, game}

false ->
{:error, :not_allowed}
end
end
end
20 changes: 20 additions & 0 deletions lib/web/controllers/hosted/page_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule Web.Hosted.PageController do
use Web, :controller

alias Web.Hosted

action_fallback(Web.FallbackController)

def index(conn, _params) do
%{current_game: game} = conn.assigns

conn
|> put_layout("hosted.html")
|> put_view(Hosted.GameView)
|> assign(:game, game)
|> assign(:title, game.name)
|> assign(:open_graph_title, game.name)
|> assign(:open_graph_description, "#{game.name} on Grapevine")
|> render("show.html")
end
end
37 changes: 37 additions & 0 deletions lib/web/controllers/hosted/play_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule Web.Hosted.PlayController do
use Web, :controller

alias Grapevine.Games
alias Web.Game

action_fallback(Web.FallbackController)

def show(conn, _params) do
with {:ok, game} <- Games.get_by_host(conn.host),
{:ok, game} <- Games.check_web_client(game),
{:ok, game} <- check_user_allowed(conn, game) do
conn
|> assign(:game, game)
|> assign(:title, "Play #{game.name}")
|> assign(:open_graph_title, game.name)
|> assign(:open_graph_description, "Play #{game.name} on Grapevine")
|> assign(:open_graph_url, play_url(conn, :show, game.short_name))
|> put_layout("hosted-play.html")
|> put_view(Web.PlayView)
|> render("show.html")
else
{:error, _} ->
{:error, :not_found}
end
end

defp check_user_allowed(conn, game) do
case Game.client_allowed?(game, conn.assigns, :current_user) do
true ->
{:ok, game}

false ->
{:error, :not_allowed}
end
end
end
25 changes: 5 additions & 20 deletions lib/web/controllers/page_controller.ex
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
defmodule Web.PageController do
use Web, :controller

alias Grapevine.CNAMEs
alias Grapevine.Games

action_fallback(Web.FallbackController)

@config Application.get_env(:grapevine, :web)[:url]

def index(conn, _params) do
case conn.host == @config[:host] do
true ->
games = Games.public(filter: %{"online" => "yes", "cover" => "yes"})

conn
|> assign(:games, games)
|> render("index.html")

false ->
case CNAMEs.host_known?(conn.host) do
true ->
redirect(conn, to: Routes.play_path(conn, :client))

false ->
{:error, :not_found}
end
end
games = Games.public(filter: %{"online" => "yes", "cover" => "yes"})

conn
|> assign(:games, games)
|> render("index.html")
end

def conduct(conn, _params) do
Expand Down
2 changes: 1 addition & 1 deletion lib/web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ defmodule Web.Endpoint do
signing_salt: "8eezNeWe"
)

plug(Web.Router)
plug(Web.SplitRouter)

@doc """
Callback invoked for dynamically configuring the endpoint.
Expand Down
26 changes: 26 additions & 0 deletions lib/web/routers/client_router.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule Web.ClientRouter do
@moduledoc """
Router for client sites
"""

use Web, :router

pipeline :browser do
plug(:accepts, ["html", "json"])
plug(:fetch_session)
plug(:fetch_flash)
plug(Phoenix.LiveView.Flash)
plug(:protect_from_forgery)
plug(:put_secure_browser_headers)
plug(Web.Plugs.FetchUser)
plug(Web.Plugs.SessionToken)
end

scope "/", Web.Client do
pipe_through([:browser])

get("/", PageController, :index)

get("/client", PlayController, :show)
end
end
26 changes: 26 additions & 0 deletions lib/web/routers/hosted_router.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule Web.HostedRouter do
@moduledoc """
Router for hosted sites
"""

use Web, :router

pipeline :browser do
plug(:accepts, ["html", "json"])
plug(:fetch_session)
plug(:fetch_flash)
plug(Phoenix.LiveView.Flash)
plug(:protect_from_forgery)
plug(:put_secure_browser_headers)
plug(Web.Plugs.FetchUser)
plug(Web.Plugs.SessionToken)
end

scope "/", Web.Hosted do
pipe_through([:browser])

get("/", PageController, :index)

get("/client", PlayController, :show)
end
end
22 changes: 1 addition & 21 deletions lib/web/router.ex → lib/web/routers/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,10 @@ defmodule Web.Router do
plug Web.Plugs.SessionToken
end

pipeline :cname do
plug(:accepts, ["html", "json"])
plug(:fetch_session)
plug(:fetch_flash)
plug(Phoenix.LiveView.Flash)
plug(:protect_from_forgery)
plug(:put_secure_browser_headers)
plug(Web.Plugs.FetchUser)
end

scope "/", Web do
pipe_through([:cname])
pipe_through([:browser])

get("/", PageController, :index)
end

scope "/", Web do
pipe_through([:cname, :session_token])

get("/client", PlayController, :client)
end

scope "/", Web do
pipe_through([:browser])

get("/conduct", PageController, :conduct)

Expand Down
49 changes: 49 additions & 0 deletions lib/web/routers/split_router.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule Web.SplitRouter do
@moduledoc """
Select the proper router based on the host header
"""

import Plug.Conn
import Phoenix.Controller

alias Grapevine.CNAMEs
alias Grapevine.Games

@config Application.get_env(:grapevine, :web)[:url]

def init(default), do: default

def call(conn, _opts) do
case conn.host == @config[:host] do
true ->
Web.Router.call(conn, %{})

false ->
case CNAMEs.type_of_host(conn.host) do
{:ok, :client, game_id} ->
{:ok, game} = Games.get(game_id)

conn = assign(conn, :current_game, game)

Web.ClientRouter.call(conn, %{})

{:ok, :site, game_id} ->
{:ok, game} = Games.get(game_id)

conn = assign(conn, :current_game, game)

Web.HostedRouter.call(conn, %{})

{:error, :not_found} ->
conn
|> fetch_session()
|> fetch_flash()
|> put_format("html")
|> put_status(:not_found)
|> put_layout({Web.LayoutView, "app.html"})
|> put_view(Web.ErrorView)
|> render(:"404")
end
end
end
end
Loading

0 comments on commit 9f30ab1

Please sign in to comment.