mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
All the way baby
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
defmodule FzCommonTest do
|
||||
use ExUnit.Case
|
||||
doctest FzCommon
|
||||
|
||||
# XXX: Ensure command injection is NOT POSSIBLE
|
||||
end
|
||||
|
||||
@@ -24,6 +24,7 @@ defmodule FzHttpWeb do
|
||||
import Plug.Conn
|
||||
import FzHttpWeb.Gettext
|
||||
import Phoenix.LiveView.Controller
|
||||
import FzHttpWeb.ControllerHelpers
|
||||
alias FzHttpWeb.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
44
apps/fz_http/lib/fz_http_web/controller_helpers.ex
Normal file
44
apps/fz_http/lib/fz_http_web/controller_helpers.ex
Normal file
@@ -0,0 +1,44 @@
|
||||
defmodule FzHttpWeb.ControllerHelpers do
|
||||
@moduledoc """
|
||||
Useful helpers for controllers
|
||||
"""
|
||||
|
||||
import Plug.Conn,
|
||||
only: [
|
||||
get_session: 2,
|
||||
put_resp_content_type: 2,
|
||||
send_resp: 3,
|
||||
halt: 1
|
||||
]
|
||||
|
||||
import Phoenix.Controller,
|
||||
only: [
|
||||
redirect: 2
|
||||
]
|
||||
|
||||
alias FzHttpWeb.Router.Helpers, as: Routes
|
||||
|
||||
def redirect_unauthenticated(conn, _options) do
|
||||
case get_session(conn, :user_id) do
|
||||
nil ->
|
||||
conn
|
||||
|> redirect(to: Routes.session_path(conn, :new))
|
||||
|
||||
_ ->
|
||||
conn
|
||||
end
|
||||
end
|
||||
|
||||
def require_authenticated(conn, _options) do
|
||||
case get_session(conn, :user_id) do
|
||||
nil ->
|
||||
conn
|
||||
|> put_resp_content_type("text/plain")
|
||||
|> send_resp(403, "Forbidden")
|
||||
|> halt()
|
||||
|
||||
_ ->
|
||||
conn
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
defmodule FzHttpWeb.AccountController do
|
||||
@moduledoc """
|
||||
Handles account-related operations
|
||||
"""
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
plug :redirect_unauthenticated
|
||||
end
|
||||
@@ -4,6 +4,8 @@ defmodule FzHttpWeb.DeviceController do
|
||||
"""
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
plug :redirect_unauthenticated
|
||||
|
||||
def index(conn, _params) do
|
||||
render(conn, "index.html", nav_active: "Devices", page_heading: "Devices")
|
||||
end
|
||||
|
||||
@@ -4,6 +4,8 @@ defmodule FzHttpWeb.RuleController do
|
||||
"""
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
plug :redirect_unauthenticated
|
||||
|
||||
def index(conn, _params) do
|
||||
render(conn, "index.html", page_heading: "Rules")
|
||||
end
|
||||
|
||||
@@ -3,13 +3,40 @@ defmodule FzHttpWeb.SessionController do
|
||||
Implements the CRUD for a Session
|
||||
"""
|
||||
|
||||
alias FzHttp.Users
|
||||
alias FzHttp.{Sessions, Users}
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
plug :put_root_layout, "auth.html"
|
||||
|
||||
def new(conn, _params) do
|
||||
render(conn, "new.html")
|
||||
changeset = Sessions.new_session()
|
||||
render(conn, "new.html", changeset: changeset)
|
||||
end
|
||||
|
||||
# POST /sessions
|
||||
def create(conn, %{"session" => %{"email" => email, "password" => password}}) do
|
||||
case Sessions.get_session(email: email) do
|
||||
nil ->
|
||||
conn
|
||||
|> put_flash(:error, "Email not found.")
|
||||
|> assign(:changeset, Sessions.new_session())
|
||||
|> render("new.html")
|
||||
|
||||
record ->
|
||||
case Sessions.create_session(record, %{email: email, password: password}) do
|
||||
{:ok, session} ->
|
||||
conn
|
||||
|> clear_session()
|
||||
|> put_session(:user_id, session.id)
|
||||
|> redirect(to: Routes.device_path(conn, :index))
|
||||
|
||||
{:error, _changeset} ->
|
||||
conn
|
||||
|> put_flash(:error, "Error signing in. Ensure email and password are correct.")
|
||||
|> assign(:changeset, Sessions.new_session())
|
||||
|> render("new.html")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# GET /sign_in/:token
|
||||
@@ -19,13 +46,12 @@ defmodule FzHttpWeb.SessionController do
|
||||
conn
|
||||
|> clear_session()
|
||||
|> put_session(:user_id, user.id)
|
||||
|> put_flash(:info, "Signed in successfully.")
|
||||
|> redirect(to: Routes.root_index_path(conn, :index))
|
||||
|> redirect(to: Routes.device_path(conn, :index))
|
||||
|
||||
{:error, error_msg} ->
|
||||
conn
|
||||
|> put_flash(:error, error_msg)
|
||||
|> redirect(to: Routes.session_new_path(conn, :new))
|
||||
|> redirect(to: Routes.session_path(conn, :new))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ defmodule FzHttpWeb.UserController do
|
||||
alias FzHttp.Users
|
||||
use FzHttpWeb, :controller
|
||||
|
||||
plug :redirect_unauthenticated
|
||||
plug :require_authenticated
|
||||
|
||||
def delete(conn, _params) do
|
||||
user_id = get_session(conn, :user_id)
|
||||
@@ -18,27 +18,13 @@ defmodule FzHttpWeb.UserController do
|
||||
conn
|
||||
|> clear_session()
|
||||
|> put_flash(:info, "Account deleted successfully.")
|
||||
|> redirect(to: Routes.root_index_path(conn, :index))
|
||||
|> redirect(to: Routes.session_path(conn, :new))
|
||||
|
||||
# delete_user is unlikely to fail, if so write a test for it and uncomment this
|
||||
# {:error, msg} ->
|
||||
# conn
|
||||
# |> clear_session()
|
||||
# |> put_flash(:error, "Error deleting account: #{msg}")
|
||||
# |> redirect(to: Routes.root_index_path(conn, :index))
|
||||
end
|
||||
end
|
||||
|
||||
def redirect_unauthenticated(conn, _options) do
|
||||
case get_session(conn, :user_id) do
|
||||
nil ->
|
||||
conn
|
||||
|> put_resp_content_type("text/plain")
|
||||
|> send_resp(403, "Forbidden")
|
||||
|> halt()
|
||||
|
||||
_ ->
|
||||
{:error, msg} ->
|
||||
conn
|
||||
|> clear_session()
|
||||
|> put_flash(:error, "Error deleting account: #{msg}")
|
||||
|> redirect(to: Routes.session_path(conn, :new))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,9 @@ defmodule FzHttpWeb.AccountLive.Show do
|
||||
|
||||
@impl true
|
||||
def mount(params, session, socket) do
|
||||
{:ok, assign_defaults(params, session, socket, &load_data/2)}
|
||||
{:ok,
|
||||
socket
|
||||
|> assign_defaults(params, session, &load_data/2)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
||||
@@ -7,7 +7,10 @@ defmodule FzHttpWeb.DeviceLive.Index do
|
||||
alias FzHttp.Devices
|
||||
|
||||
def mount(params, session, socket) do
|
||||
{:ok, assign_defaults(params, session, socket, &load_data/2)}
|
||||
{:ok,
|
||||
socket
|
||||
|> assign_defaults(params, session, &load_data/2)
|
||||
|> assign(:page_heading, "Devices")}
|
||||
end
|
||||
|
||||
def handle_event("create_device", _params, socket) do
|
||||
|
||||
@@ -8,7 +8,9 @@ defmodule FzHttpWeb.DeviceLive.Show do
|
||||
|
||||
@impl true
|
||||
def mount(params, session, socket) do
|
||||
{:ok, assign_defaults(params, session, socket, &load_data/2)}
|
||||
{:ok,
|
||||
socket
|
||||
|> assign_defaults(params, session, &load_data/2)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
||||
@@ -5,6 +5,8 @@ defmodule FzHttpWeb.RuleLive.Index do
|
||||
use FzHttpWeb, :live_view
|
||||
|
||||
def mount(params, session, socket) do
|
||||
{:ok, assign_defaults(params, session, socket)}
|
||||
{:ok,
|
||||
socket
|
||||
|> assign_defaults(params, session)}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,15 +34,6 @@ defmodule FzHttpWeb.SessionLive.New do
|
||||
end
|
||||
end
|
||||
|
||||
# Guess email if signups are disabled and only one user exists
|
||||
def email_field_opts(opts \\ []) do
|
||||
if Users.single_user?() and signups_disabled?() do
|
||||
opts ++ [value: Users.admin_email()]
|
||||
else
|
||||
opts
|
||||
end
|
||||
end
|
||||
|
||||
defp redirect_to_sign_in(socket, session) do
|
||||
case create_sign_in_token(session) do
|
||||
{:ok, token} ->
|
||||
@@ -68,10 +59,6 @@ defmodule FzHttpWeb.SessionLive.New do
|
||||
end
|
||||
end
|
||||
|
||||
defp signups_disabled? do
|
||||
Application.fetch_env!(:fz_http, :disable_signup)
|
||||
end
|
||||
|
||||
defp sign_in_params do
|
||||
FzMap.stringify_keys(Users.sign_in_keys())
|
||||
end
|
||||
|
||||
@@ -5,11 +5,6 @@ defmodule FzHttpWeb.Router do
|
||||
|
||||
use FzHttpWeb, :router
|
||||
|
||||
# View emails locally in development
|
||||
if Mix.env() == :dev do
|
||||
forward "/sent_emails", Bamboo.SentEmailViewerPlug
|
||||
end
|
||||
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
@@ -27,23 +22,18 @@ defmodule FzHttpWeb.Router do
|
||||
pipe_through :browser
|
||||
|
||||
get "/", DeviceController, :index
|
||||
get "/devices", DeviceController, :index
|
||||
get "/rules", RuleController, :index
|
||||
get "/session/new", SessionController, :new
|
||||
resources "/session", SessionController, only: [:new, :create, :delete]
|
||||
|
||||
# live "/sign_in", SessionLive.New, :new
|
||||
# live "/sign_up", UserLive.New, :new
|
||||
# live "/account", AccountLive.Show, :show
|
||||
# live "/account/edit", AccountLive.Show, :edit
|
||||
live "/account", AccountLive.Show, :show
|
||||
live "/account/edit", AccountLive.Show, :edit
|
||||
|
||||
# live "/rules", RuleLive.Index, :index
|
||||
live "/rules", RuleLive.Index, :index
|
||||
|
||||
# live "/devices", DeviceLive.Index, :index
|
||||
# live "/devices/:id", DeviceLive.Show, :show
|
||||
# live "/devices/:id/edit", DeviceLive.Show, :edit
|
||||
live "/devices", DeviceLive.Index, :index
|
||||
live "/devices/:id", DeviceLive.Show, :show
|
||||
live "/devices/:id/edit", DeviceLive.Show, :edit
|
||||
|
||||
get "/sign_in/:token", SessionController, :create
|
||||
post "/sign_out", SessionController, :delete
|
||||
delete "/user", UserController, :delete
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<h1>Devices</h1>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<!-- foobar -->
|
||||
<div class="container">
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<%= csrf_meta_tag() %>
|
||||
<%= live_title_tag assigns[:page_title] || "FireZone" %>
|
||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<h4 class="title is-4 navbar-item">
|
||||
FireZone
|
||||
</h4>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<%= if assigns[:current_user] do %>
|
||||
<div class="navbar-start">
|
||||
<%= live_redirect("Devices", to: Routes.device_index_path(@conn, :index), class: "navbar-item") %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
<%= if assigns[:current_user] do %>
|
||||
<div class="navbar-item">
|
||||
<%= live_redirect("Your Account", to: Routes.account_show_path(@conn, :show)) %>
|
||||
</div>
|
||||
<div class="navbar-item">
|
||||
<%= link("Sign out", to: Routes.session_path(@conn, :delete), method: :post) %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="navbar-item">
|
||||
<%= live_redirect("Sign in", to: Routes.session_new_path(@conn, :new)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<section class="section">
|
||||
<%= @inner_content %>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
@@ -62,10 +62,10 @@
|
||||
<span>Messages</span>
|
||||
</a>
|
||||
<hr class="navbar-divider">
|
||||
<a class="navbar-item">
|
||||
<%= link(to: Routes.session_path(@conn, :delete, "noop"), method: :delete, class: "navbar-item") do %>
|
||||
<span class="icon"><i class="mdi mdi-logout"></i></span>
|
||||
<span>Log Out</span>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbar-item has-dropdown has-dropdown-with-icons has-divider has-user-avatar is-hoverable">
|
||||
@@ -130,13 +130,13 @@
|
||||
<p class="menu-label">Configuration</p>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<%= link(to: Routes.device_path(@conn, :index), class: nav_class(@conn.request_path, :devices)) do %>
|
||||
<%= link(to: Routes.device_index_path(@conn, :index), class: nav_class(@conn.request_path, :devices)) do %>
|
||||
<span class="icon has-update-mark"><i class="mdi mdi-table"></i></span>
|
||||
<span class="menu-item-label">Devices</span>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link(to: Routes.rule_path(@conn, :index), class: nav_class(@conn.request_path, :rules)) do %>
|
||||
<%= link(to: Routes.rule_index_path(@conn, :index), class: nav_class(@conn.request_path, :rules)) do %>
|
||||
<span class="icon"><i class="mdi mdi-square-edit-outline"></i></span>
|
||||
<span class="menu-item-label">Rules</span>
|
||||
<% end %>
|
||||
@@ -144,12 +144,6 @@
|
||||
</ul>
|
||||
<p class="menu-label">Settings</p>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<a href="https://admin-one-html.justboil.me/" target="_blank" class="has-icon">
|
||||
<span class="icon"><i class="mdi mdi-credit-card-outline"></i></span>
|
||||
<span class="menu-item-label">Admin</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://justboil.me/bulma-admin-template/one-html" class="has-icon">
|
||||
<span class="icon"><i class="mdi mdi-help-circle"></i></span>
|
||||
@@ -197,6 +191,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section is-main-section">
|
||||
<%= @inner_content %>
|
||||
</section>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
<div class="level">
|
||||
@@ -213,7 +212,7 @@
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
<div class="logo">
|
||||
<a href="https://justboil.me"><img src="images/logo.svg" alt="firez.one"></a>
|
||||
<a href="https://firez.one"><img src="images/logo.svg" alt="firez.one"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<h3 class="title">Sign In</h3>
|
||||
<hr>
|
||||
|
||||
<%= form_for @changeset, "#", [id: "sign-in", phx_submit: :sign_in], fn f -> %>
|
||||
<%= form_for @changeset, Routes.session_path(@conn, :create), fn f -> %>
|
||||
<%= if assigns[:changeset] && @changeset.action do %>
|
||||
<div>
|
||||
<p>Oops, something went wrong! Please check the errors below.</p>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
defmodule FzHttpWeb.EmailView do
|
||||
use FzHttpWeb, :view
|
||||
end
|
||||
@@ -16,7 +16,6 @@ defmodule FzHttpWeb.LayoutView do
|
||||
def nav_class("/", :devices), do: "is-active has-icon"
|
||||
def nav_class("/devices", :devices), do: "is-active has-icon"
|
||||
def nav_class("/rules", :rules), do: "is-active has-icon"
|
||||
def nav_class("/admin", :admin), do: "is-active has-icon"
|
||||
def nav_class("/account", :account), do: "is-active has-icon"
|
||||
def nav_class(_, _), do: "has-icon"
|
||||
end
|
||||
|
||||
@@ -10,7 +10,7 @@ defmodule FzHttpWeb.LiveHelpers do
|
||||
@doc """
|
||||
Load user into socket assigns and call the callback function if provided.
|
||||
"""
|
||||
def assign_defaults(params, %{"user_id" => user_id}, socket, callback) do
|
||||
def assign_defaults(socket, params, %{"user_id" => user_id}, callback) do
|
||||
socket = assign_new(socket, :current_user, fn -> Users.get_user(user_id) end)
|
||||
|
||||
if socket.assigns.current_user do
|
||||
@@ -20,22 +20,22 @@ defmodule FzHttpWeb.LiveHelpers do
|
||||
end
|
||||
end
|
||||
|
||||
def assign_defaults(_params, _session, socket, _decorator) do
|
||||
def assign_defaults(socket, _params, _session, _decorator) do
|
||||
not_authorized(socket)
|
||||
end
|
||||
|
||||
def assign_defaults(_params, %{"user_id" => user_id}, socket) do
|
||||
def assign_defaults(socket, _params, %{"user_id" => user_id}) do
|
||||
assign_new(socket, :current_user, fn -> Users.get_user!(user_id) end)
|
||||
end
|
||||
|
||||
def assign_defaults(_params, _session, socket) do
|
||||
def assign_defaults(socket, _params, _session) do
|
||||
not_authorized(socket)
|
||||
end
|
||||
|
||||
def not_authorized(socket) do
|
||||
socket
|
||||
|> put_flash(:error, "Not authorized.")
|
||||
|> redirect(to: Routes.session_new_path(socket, :new))
|
||||
|> redirect(to: Routes.session_path(socket, :new))
|
||||
end
|
||||
|
||||
def live_modal(component, opts) do
|
||||
|
||||
14
apps/fz_http/lib/fz_http_web/views/session_view.ex
Normal file
14
apps/fz_http/lib/fz_http_web/views/session_view.ex
Normal file
@@ -0,0 +1,14 @@
|
||||
defmodule FzHttpWeb.SessionView do
|
||||
use FzHttpWeb, :view
|
||||
|
||||
alias FzHttp.Users
|
||||
|
||||
# Guess email if signups are disabled and only one user exists
|
||||
def email_field_opts(opts \\ []) do
|
||||
if Users.single_user?() do
|
||||
opts ++ [value: Users.admin_email()]
|
||||
else
|
||||
opts
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -37,6 +37,10 @@ defmodule FzWall.CLI.Live do
|
||||
exec!("iptables -A firezone -s #{s} -d #{d} -j DROP")
|
||||
end
|
||||
|
||||
def add_rule({4, d, :deny}) do
|
||||
exec!("iptables -A firezone -d #{d} -j DROP")
|
||||
end
|
||||
|
||||
def add_rule({4, s, d, :allow}) do
|
||||
exec!("iptables -A firezone -s #{s} -d #{d} -j ACCEPT")
|
||||
end
|
||||
|
||||
@@ -9,8 +9,6 @@ config :fz_http, FzHttp.Repo,
|
||||
show_sensitive_data_on_connection_error: true,
|
||||
pool_size: 10
|
||||
|
||||
config :fz_http, FzHttp.Mailer, adapter: Bamboo.LocalAdapter
|
||||
|
||||
# For development, we disable any cache and enable
|
||||
# debugging and code reloading.
|
||||
#
|
||||
|
||||
@@ -27,8 +27,6 @@ end
|
||||
db_url = System.get_env("DATABASE_URL")
|
||||
config :fz_http, FzHttp.Repo, DBConfig.config(db_url)
|
||||
|
||||
config :fz_http, FzHttp.Mailer, adapter: Bamboo.TestAdapter
|
||||
|
||||
# We don't run a server during test. If one is required,
|
||||
# you can enable the server option below.
|
||||
config :fz_http, FzHttpWeb.Endpoint,
|
||||
|
||||
@@ -3,10 +3,14 @@ set -e
|
||||
|
||||
# Required due to a buildx bug.
|
||||
# See https://github.com/docker/buildx/issues/495#issuecomment-761562905
|
||||
docker buildx rm multiarch || true
|
||||
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
docker buildx create --name multiarch --driver docker-container --use
|
||||
docker buildx inspect --bootstrap
|
||||
if [ `uname -m` = "amd64" ]; then
|
||||
docker buildx rm multiarch || true
|
||||
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
docker buildx create --name multiarch --driver docker-container --use
|
||||
docker buildx inspect --bootstrap
|
||||
elif [ `uname -m` = "arm64" ]; then
|
||||
docker buildx create --use
|
||||
fi
|
||||
.ci/build_amazonlinux_2.base.sh
|
||||
.ci/build_centos_7.base.sh
|
||||
.ci/build_centos_8.base.sh
|
||||
|
||||
Reference in New Issue
Block a user