diff --git a/apps/fg_http/lib/fg_http/devices.ex b/apps/fg_http/lib/fg_http/devices.ex
index 72ec5a3b7..65d0367af 100644
--- a/apps/fg_http/lib/fg_http/devices.ex
+++ b/apps/fg_http/lib/fg_http/devices.ex
@@ -52,6 +52,14 @@ defmodule FgHttp.Devices do
"""
def get_device!(id), do: Repo.get!(Device, id)
+ def get_device!(id, with_rules: true) do
+ Repo.one(
+ from d in Device,
+ where: d.id == ^id,
+ preload: :rules
+ )
+ end
+
@doc """
Creates a device.
diff --git a/apps/fg_http/lib/fg_http/devices/device.ex b/apps/fg_http/lib/fg_http/devices/device.ex
index 5be9fdbb0..a06ba621e 100644
--- a/apps/fg_http/lib/fg_http/devices/device.ex
+++ b/apps/fg_http/lib/fg_http/devices/device.ex
@@ -6,13 +6,15 @@ defmodule FgHttp.Devices.Device do
use Ecto.Schema
import Ecto.Changeset
+ alias FgHttp.{Rules.Rule, Users.User}
+
schema "devices" do
field :name, :string
field :public_key, :string
- field :user_id, :id
field :last_ip, :map
- has_many :rules, FgHttp.Rules.Rule
+ has_many :rules, Rule
+ belongs_to :user, User
timestamps()
end
diff --git a/apps/fg_http/lib/fg_http/ecto_enums.ex b/apps/fg_http/lib/fg_http/ecto_enums.ex
new file mode 100644
index 000000000..579ce3acd
--- /dev/null
+++ b/apps/fg_http/lib/fg_http/ecto_enums.ex
@@ -0,0 +1,18 @@
+import EctoEnum
+
+# We only allow dropping or accepting packets for now
+defenum(RuleActionEnum, :action, [:drop, :accept])
+
+# See http://ipset.netfilter.org/iptables.man.html
+defenum(RuleProtocolEnum, :protocol, [
+ :all,
+ :tcp,
+ :udp,
+ :udplite,
+ :icmp,
+ :icmpv6,
+ :esp,
+ :ah,
+ :sctp,
+ :mh
+])
diff --git a/apps/fg_http/lib/fg_http/rules.ex b/apps/fg_http/lib/fg_http/rules.ex
index 362479eca..78f142f62 100644
--- a/apps/fg_http/lib/fg_http/rules.ex
+++ b/apps/fg_http/lib/fg_http/rules.ex
@@ -17,6 +17,10 @@ defmodule FgHttp.Rules do
[%Rule{}, ...]
"""
+ def list_rules(device_id) do
+ Repo.all(from r in Rule, where: r.device_id == ^device_id, select: "*")
+ end
+
def list_rules do
Repo.all(Rule)
end
diff --git a/apps/fg_http/lib/fg_http/rules/rule.ex b/apps/fg_http/lib/fg_http/rules/rule.ex
index b0e524322..f5b7fe1c0 100644
--- a/apps/fg_http/lib/fg_http/rules/rule.ex
+++ b/apps/fg_http/lib/fg_http/rules/rule.ex
@@ -6,13 +6,17 @@ defmodule FgHttp.Rules.Rule do
use Ecto.Schema
import Ecto.Changeset
- schema "rules" do
- field :destination, :map
- field :enabled, :boolean, default: false
- field :port, :string
- field :protocol, :string
+ alias FgHttp.{Devices.Device}
- belongs_to :device, FgHttp.Devices.Device
+ schema "rules" do
+ field :destination, EctoNetwork.INET
+ field :action, RuleActionEnum, default: "drop"
+ field :priority, :integer, default: 0
+ field :enabled, :boolean, default: true
+ field :port, :string
+ field :protocol, RuleProtocolEnum, default: "all"
+
+ belongs_to :device, Device
timestamps()
end
@@ -20,7 +24,7 @@ defmodule FgHttp.Rules.Rule do
@doc false
def changeset(rule, attrs) do
rule
- |> cast(attrs, [:destination, :port, :protocol, :enabled])
- |> validate_required([:destination, :enabled])
+ |> cast(attrs, [:device_id, :priority, :action, :destination, :port, :protocol, :enabled])
+ |> validate_required([:device_id, :priority, :action, :destination, :protocol, :enabled])
end
end
diff --git a/apps/fg_http/lib/fg_http/sessions/session.ex b/apps/fg_http/lib/fg_http/sessions/session.ex
index e9f2174a1..506e6075c 100644
--- a/apps/fg_http/lib/fg_http/sessions/session.ex
+++ b/apps/fg_http/lib/fg_http/sessions/session.ex
@@ -6,8 +6,10 @@ defmodule FgHttp.Sessions.Session do
use Ecto.Schema
import Ecto.Changeset
+ alias FgHttp.{Users.User}
+
schema "sessions" do
- field :user_id, :id
+ belongs_to :user, User
timestamps()
end
diff --git a/apps/fg_http/lib/fg_http/users/user.ex b/apps/fg_http/lib/fg_http/users/user.ex
index c4fe12691..2df6319fe 100644
--- a/apps/fg_http/lib/fg_http/users/user.ex
+++ b/apps/fg_http/lib/fg_http/users/user.ex
@@ -6,12 +6,17 @@ defmodule FgHttp.Users.User do
use Ecto.Schema
import Ecto.Changeset
+ alias FgHttp.{Devices.Device, Sessions.Session}
+
schema "users" do
field :email, :string
field :confirmed_at, :utc_datetime
field :last_signed_in_at, :utc_datetime
field :password_digest, :string
+ has_many :devices, Device
+ has_many :sessions, Session
+
timestamps()
end
diff --git a/apps/fg_http/lib/fg_http_web/controllers/rule_controller.ex b/apps/fg_http/lib/fg_http_web/controllers/rule_controller.ex
index 129ebfb0b..3d53ed9d2 100644
--- a/apps/fg_http/lib/fg_http_web/controllers/rule_controller.ex
+++ b/apps/fg_http/lib/fg_http_web/controllers/rule_controller.ex
@@ -9,8 +9,7 @@ defmodule FgHttpWeb.RuleController do
plug FgHttpWeb.Plugs.Authenticator
def index(conn, %{"device_id" => device_id}) do
- device = Devices.get_device!(device_id)
-
+ device = Devices.get_device!(device_id, with_rules: true)
render(conn, "index.html", device: device, rules: device.rules)
end
diff --git a/apps/fg_http/lib/fg_http_web/templates/device/show.html.eex b/apps/fg_http/lib/fg_http_web/templates/device/show.html.eex
index 8db5dae66..03c74a793 100644
--- a/apps/fg_http/lib/fg_http_web/templates/device/show.html.eex
+++ b/apps/fg_http/lib/fg_http_web/templates/device/show.html.eex
@@ -12,5 +12,9 @@
-<%= link "Edit", to: Routes.device_path(@conn, :edit, @device) %>
-<%= link "Back", to: Routes.device_path(@conn, :index) %>
+
+ <%= link "Show Rules for This Device", to: Routes.device_rule_path(@conn, :index, @device) %>
+
+
+<%= link "Edit", to: Routes.device_path(@conn, :edit, @device) %>
+<%= link "Back", to: Routes.device_path(@conn, :index) %>
diff --git a/apps/fg_http/lib/fg_http_web/templates/rule/form.html.eex b/apps/fg_http/lib/fg_http_web/templates/rule/form.html.eex
index 8a4461fbf..bdf4a802a 100644
--- a/apps/fg_http/lib/fg_http_web/templates/rule/form.html.eex
+++ b/apps/fg_http/lib/fg_http_web/templates/rule/form.html.eex
@@ -1,27 +1,41 @@
-<%= form_for @changeset, @action, fn f -> %>
+<%= form_for @changeset, @action, [class: "black-80"], fn f -> %>
<%= if @changeset.action do %>
-
+
Oops, something went wrong! Please check the errors below.
<% end %>
- <%= label f, :destination %>
- <%= text_input f, :destination %>
- <%= error_tag f, :destination %>
+
+ <%= label f, :destination, class: "f6 b db mb2" %>
+ <%= text_input f, :destination, class: "input-reset ba b--black-20 pa2 mb2 db w-100" %>
+ <%= error_tag f, :destination %>
+
- <%= label f, :port %>
- <%= text_input f, :port %>
- <%= error_tag f, :port %>
+
+ <%= label f, :port, class: "f6 b db mb2" %>
+ <%= text_input f, :port, class: "input-reset ba b--black-20 pa2 mb2 db w-100" %>
+ <%= error_tag f, :port %>
+
- <%= label f, :protocol %>
- <%= text_input f, :protocol %>
- <%= error_tag f, :protocol %>
+
+ <%= label f, :protocol, class: "f6 b db mb2" %>
+ <%= text_input f, :protocol, class: "input-reset ba b--black-20 pa2 mb2 db w-100" %>
+ <%= error_tag f, :protocol %>
+
- <%= label f, :enabled %>
- <%= checkbox f, :enabled %>
- <%= error_tag f, :enabled %>
+
+ <%= label f, :priority, class: "f6 b db mb2" %>
+ <%= text_input f, :priority, class: "input-reset ba b--black-20 pa2 mb2 db w-100" %>
+ <%= error_tag f, :priority %>
+
-
+
+ <%= label f, :enabled, class: "f6 b db mb2" %>
+ <%= checkbox f, :enabled %>
+ <%= error_tag f, :enabled %>
+
+
+
<%= submit "Save" %>
<% end %>
diff --git a/apps/fg_http/lib/fg_http_web/templates/rule/index.html.eex b/apps/fg_http/lib/fg_http_web/templates/rule/index.html.eex
index 63ab8b4e3..a38306450 100644
--- a/apps/fg_http/lib/fg_http_web/templates/rule/index.html.eex
+++ b/apps/fg_http/lib/fg_http_web/templates/rule/index.html.eex
@@ -1,23 +1,21 @@
-
Listing Rules
+
Listing Rules for Device <%= @device.name %>
-
-
-
- | Destination |
- Port |
- Protocol |
- Enabled |
+
+
+
+ | Destination |
+ Port |
+ Protocol |
+ Enabled |
|
-
-
<%= for rule <- @rules do %>
-
- | <%= rule.destination %> |
- <%= rule.port %> |
- <%= rule.protocol %> |
- <%= rule.enabled %> |
+
+ | <%= rule.destination %> |
+ <%= rule.port %> |
+ <%= rule.protocol %> |
+ <%= rule.enabled %> |
<%= link "Show", to: Routes.rule_path(@conn, :show, rule) %>
@@ -30,5 +28,5 @@
|
- <%= link "New Rule", to: Routes.rule_path(@conn, :new, @device) %>
+ <%= link "New Rule", to: Routes.device_rule_path(@conn, :new, @device) %>
diff --git a/apps/fg_http/lib/fg_http_web/templates/rule/new.html.eex b/apps/fg_http/lib/fg_http_web/templates/rule/new.html.eex
index 5c88667cd..e7963ed7d 100644
--- a/apps/fg_http/lib/fg_http_web/templates/rule/new.html.eex
+++ b/apps/fg_http/lib/fg_http_web/templates/rule/new.html.eex
@@ -1,5 +1,5 @@
-New Rule
+New Rule for Device <%= @device.name %>
-<%= render "form.html", Map.put(assigns, :action, Routes.rule_path(@conn, :create, @device)) %>
+<%= render "form.html", Map.put(assigns, :action, Routes.device_rule_path(@conn, :create, @device)) %>
-<%= link "Back", to: Routes.rule_path(@conn, :index, @device) %>
+<%= link "Back", to: Routes.device_rule_path(@conn, :index, @device) %>
diff --git a/apps/fg_http/mix.exs b/apps/fg_http/mix.exs
index f9896260a..e0bbd12d3 100644
--- a/apps/fg_http/mix.exs
+++ b/apps/fg_http/mix.exs
@@ -41,6 +41,8 @@ defmodule FgHttp.MixProject do
{:phoenix_pubsub, "~> 2.0"},
{:phoenix_ecto, "~> 4.0"},
{:ecto_sql, "~> 3.1"},
+ {:ecto_enum, "~> 1.4.0"},
+ {:ecto_network, "~> 1.3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.11"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
diff --git a/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs b/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs
index 931569ea6..1b0c692d9 100644
--- a/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs
+++ b/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs
@@ -6,7 +6,7 @@ defmodule FgHttp.Repo.Migrations.CreateDevices do
add :name, :string
add :public_key, :string
add :last_ip, :inet
- add :user_id, references(:users, on_delete: :delete_all)
+ add :user_id, references(:users, on_delete: :delete_all), null: false
timestamps()
end
diff --git a/apps/fg_http/priv/repo/migrations/20200228154815_create_rules.exs b/apps/fg_http/priv/repo/migrations/20200228154815_create_rules.exs
index e83298300..eda009fb9 100644
--- a/apps/fg_http/priv/repo/migrations/20200228154815_create_rules.exs
+++ b/apps/fg_http/priv/repo/migrations/20200228154815_create_rules.exs
@@ -2,12 +2,17 @@ defmodule FgHttp.Repo.Migrations.CreateRules do
use Ecto.Migration
def change do
+ RuleActionEnum.create_type()
+ RuleProtocolEnum.create_type()
+
create table(:rules) do
add :destination, :inet
- add :port, :string
- add :protocol, :string
+ add :protocol, RuleProtocolEnum.type(), default: "all", null: false
+ add :action, RuleActionEnum.type(), default: "drop", null: false
+ add :priority, :integer, default: 0, null: false
add :enabled, :boolean, default: false, null: false
- add :device_id, references(:devices, on_delete: :delete_all)
+ add :port, :string
+ add :device_id, references(:devices, on_delete: :delete_all), null: false
timestamps()
end
diff --git a/apps/fg_http/priv/repo/seeds.exs b/apps/fg_http/priv/repo/seeds.exs
index e4f1922a7..adccbb974 100644
--- a/apps/fg_http/priv/repo/seeds.exs
+++ b/apps/fg_http/priv/repo/seeds.exs
@@ -23,9 +23,9 @@ Repo.transaction(fn ->
user_id: user.id
})
- {:ok, rule} =
+ {:ok, _rule} =
FgHttp.Rules.create_rule(%{
- destination: %Postgrex.INET{address: {0, 0, 0, 0}, netmask: 0},
- device_id: device.id
+ device_id: device.id,
+ destination: %Postgrex.INET{address: {0, 0, 0, 0}, netmask: 0}
})
end)
diff --git a/mix.lock b/mix.lock
index 42340985a..11058b065 100644
--- a/mix.lock
+++ b/mix.lock
@@ -7,6 +7,7 @@
"db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"},
"decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"},
"ecto": {:hex, :ecto, "3.4.4", "a2c881e80dc756d648197ae0d936216c0308370332c5e77a2325a10293eef845", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cc4bd3ad62abc3b21fb629f0f7a3dab23a192fca837d257dd08449fba7373561"},
+ "ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
"ecto_network": {:hex, :ecto_network, "1.3.0", "1e77fa37c20e0f6a426d3862732f3317b0fa4c18f123d325f81752a491d7304e", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 0.0.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.14.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "053a5e46ef2837e8ea5ea97c82fa0f5494699209eddd764e663c85f11b2865bd"},
"ecto_sql": {:hex, :ecto_sql, "3.4.3", "c552aa8a7ccff2b64024f835503b3155d8e73452c180298527fbdbcd6e79710b", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ec9e59d6fa3f8cfda9963ada371e9e6659167c2338a997bd7ea23b10b245842b"},
"file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},