From 18e4d41a225ce8903df1f4697285404472ad30ab Mon Sep 17 00:00:00 2001 From: Jamil Bou Kheir Date: Thu, 14 May 2020 19:44:44 -0500 Subject: [PATCH 1/4] No need for ecto_network --- apps/fg_http/lib/fg_http/devices/device.ex | 3 ++- apps/fg_http/lib/fg_http/rules/rule.ex | 4 ++-- apps/fg_http/mix.exs | 2 -- .../20200228145810_create_devices.exs | 1 + apps/fg_http/priv/repo/seeds.exs | 20 +++++++++++++++++++ mix.lock | 8 ++++---- 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/apps/fg_http/lib/fg_http/devices/device.ex b/apps/fg_http/lib/fg_http/devices/device.ex index ecf4a34c5..5be9fdbb0 100644 --- a/apps/fg_http/lib/fg_http/devices/device.ex +++ b/apps/fg_http/lib/fg_http/devices/device.ex @@ -10,6 +10,7 @@ defmodule FgHttp.Devices.Device do field :name, :string field :public_key, :string field :user_id, :id + field :last_ip, :map has_many :rules, FgHttp.Rules.Rule @@ -19,7 +20,7 @@ defmodule FgHttp.Devices.Device do @doc false def changeset(device, attrs) do device - |> cast(attrs, [:user_id, :name, :public_key]) + |> cast(attrs, [:last_ip, :user_id, :name, :public_key]) |> validate_required([:user_id]) end end diff --git a/apps/fg_http/lib/fg_http/rules/rule.ex b/apps/fg_http/lib/fg_http/rules/rule.ex index 89597b348..b0e524322 100644 --- a/apps/fg_http/lib/fg_http/rules/rule.ex +++ b/apps/fg_http/lib/fg_http/rules/rule.ex @@ -7,7 +7,7 @@ defmodule FgHttp.Rules.Rule do import Ecto.Changeset schema "rules" do - field :destination, :string + field :destination, :map field :enabled, :boolean, default: false field :port, :string field :protocol, :string @@ -21,6 +21,6 @@ defmodule FgHttp.Rules.Rule do def changeset(rule, attrs) do rule |> cast(attrs, [:destination, :port, :protocol, :enabled]) - |> validate_required([:destination, :port, :protocol, :enabled]) + |> validate_required([:destination, :enabled]) end end diff --git a/apps/fg_http/mix.exs b/apps/fg_http/mix.exs index f471eef57..f9896260a 100644 --- a/apps/fg_http/mix.exs +++ b/apps/fg_http/mix.exs @@ -41,8 +41,6 @@ defmodule FgHttp.MixProject do {:phoenix_pubsub, "~> 2.0"}, {:phoenix_ecto, "~> 4.0"}, {:ecto_sql, "~> 3.1"}, - # Exposes Postgres inet, cidr, macaddr types - {: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 f2d57d058..931569ea6 100644 --- a/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs +++ b/apps/fg_http/priv/repo/migrations/20200228145810_create_devices.exs @@ -5,6 +5,7 @@ defmodule FgHttp.Repo.Migrations.CreateDevices do create table(:devices) do add :name, :string add :public_key, :string + add :last_ip, :inet add :user_id, references(:users, on_delete: :delete_all) timestamps() diff --git a/apps/fg_http/priv/repo/seeds.exs b/apps/fg_http/priv/repo/seeds.exs index 177a1aa39..e4f1922a7 100644 --- a/apps/fg_http/priv/repo/seeds.exs +++ b/apps/fg_http/priv/repo/seeds.exs @@ -9,3 +9,23 @@ # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. + +alias FgHttp.Repo + +Repo.transaction(fn -> + {:ok, user} = FgHttp.Users.create_user(%{email: "testuser@fireguard.network"}) + + {:ok, device} = + FgHttp.Devices.create_device(%{ + name: "Seed", + public_key: "Seed", + last_ip: %Postgrex.INET{address: {127, 0, 0, 1}}, + user_id: user.id + }) + + {:ok, rule} = + FgHttp.Rules.create_rule(%{ + destination: %Postgrex.INET{address: {0, 0, 0, 0}, netmask: 0}, + device_id: device.id + }) +end) diff --git a/mix.lock b/mix.lock index 9cfefa1cc..42340985a 100644 --- a/mix.lock +++ b/mix.lock @@ -6,23 +6,23 @@ "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, "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.3", "3a14c2500c3964165245a4f24a463e080762f7ccd0c632c763ea589f75ca205f", [: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", "9b6f18dea95f2004d0369f6a8346513ca3f706614f4ede219a5f3fe5db5dd962"}, + "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_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"}, - "gettext": {:hex, :gettext, "0.17.4", "f13088e1ec10ce01665cf25f5ff779e7df3f2dc71b37084976cf89d1aa124d5c", [:mix], [], "hexpm", "3c75b5ea8288e2ee7ea503ff9e30dfe4d07ad3c054576a6e60040e79a801e14d"}, + "gettext": {:hex, :gettext, "0.18.0", "406d6b9e0e3278162c2ae1de0a60270452c553536772167e2d701f028116f870", [:mix], [], "hexpm", "c3f850be6367ebe1a08616c2158affe4a23231c70391050bf359d5f92f66a571"}, "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm", "6cbe761d6a0ca5a31a0931bf4c63204bceb64538e664a8ecf784a9a6f3b875f1"}, "phoenix": {:hex, :phoenix, "1.5.1", "95156589879dc69201d5fc0ebdbfdfc7901a09a3616ea611ec297f81340275a2", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc272b38e79d2881790fccae6f67a9fbe9b790103d6878175ea03d23003152eb"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"}, "phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "58061c8dfd25da5df1ea0ca47c972f161beb6c875cd293917045b92ffe1bf617"}, - "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "41b4103a2fa282cfd747d377233baf213c648fdcc7928f432937676532490eee"}, + "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.2", "38d94c30df5e2ef11000697a4fbe2b38d0fbf79239d492ff1be87bbc33bc3a84", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "a3dec3d28ddb5476c96a7c8a38ea8437923408bc88da43e5c45d97037b396280"}, "phoenix_live_view": {:hex, :phoenix_live_view, "0.12.1", "42f591c781edbf9fab921319076b7ac635d43aa23e6748d2644563326236d7e4", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4.16 or ~> 1.5.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "585321e98df1cd5943e370b9784e950a37ca073744eb534660c9048967c52ab6"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, "plug": {:hex, :plug, "1.10.0", "6508295cbeb4c654860845fb95260737e4a8838d34d115ad76cd487584e2fc4d", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "422a9727e667be1bf5ab1de03be6fa0ad67b775b2d84ed908f3264415ef29d4a"}, "plug_cowboy": {:hex, :plug_cowboy, "2.2.1", "fcf58aa33227a4322a050e4783ee99c63c031a2e7f9a2eb7340d55505e17f30f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3b43de24460d87c0971887286e7a20d40462e48eb7235954681a20cee25ddeb6"}, "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"}, - "postgrex": {:hex, :postgrex, "0.15.3", "5806baa8a19a68c4d07c7a624ccdb9b57e89cbc573f1b98099e3741214746ae4", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "4737ce62a31747b4c63c12b20c62307e51bb4fcd730ca0c32c280991e0606c90"}, + "postgrex": {:hex, :postgrex, "0.15.4", "5d691c25fc79070705a2ff0e35ce0822b86a0ee3c6fdb7a4fb354623955e1aed", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "306515b9d975fcb2478dc337a1d27dc3bf8af7cd71017c333fe9db3a3d211b0a"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"}, } From a18b2fe212886e941f6cf4eb769e0bc1645bc830 Mon Sep 17 00:00:00 2001 From: Jamil Bou Kheir Date: Thu, 14 May 2020 23:34:18 -0500 Subject: [PATCH 2/4] Rule CRUD coming along ... --- apps/fg_http/lib/fg_http/devices.ex | 8 ++++ apps/fg_http/lib/fg_http/devices/device.ex | 6 ++- apps/fg_http/lib/fg_http/ecto_enums.ex | 18 ++++++++ apps/fg_http/lib/fg_http/rules.ex | 4 ++ apps/fg_http/lib/fg_http/rules/rule.ex | 20 +++++---- apps/fg_http/lib/fg_http/sessions/session.ex | 4 +- apps/fg_http/lib/fg_http/users/user.ex | 5 +++ .../controllers/rule_controller.ex | 3 +- .../templates/device/show.html.eex | 8 +++- .../fg_http_web/templates/rule/form.html.eex | 44 ++++++++++++------- .../fg_http_web/templates/rule/index.html.eex | 30 ++++++------- .../fg_http_web/templates/rule/new.html.eex | 6 +-- apps/fg_http/mix.exs | 2 + .../20200228145810_create_devices.exs | 2 +- .../20200228154815_create_rules.exs | 11 +++-- apps/fg_http/priv/repo/seeds.exs | 6 +-- mix.lock | 1 + 17 files changed, 122 insertions(+), 56 deletions(-) create mode 100644 apps/fg_http/lib/fg_http/ecto_enums.ex 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 %>

- - - - - - - +
DestinationPortProtocolEnabled
+ + + + + + - - <%= for rule <- @rules do %> - - - - - + + + + +
DestinationPortProtocolEnabled
<%= 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"}, From ee2c810dc023b887c38059c9141478c01f24e873 Mon Sep 17 00:00:00 2001 From: Jamil Bou Kheir Date: Fri, 15 May 2020 00:32:41 -0500 Subject: [PATCH 3/4] CRUD works yay --- apps/fg_http/lib/fg_http/devices.ex | 6 ++++-- apps/fg_http/lib/fg_http/devices/device.ex | 2 +- apps/fg_http/lib/fg_http/rules.ex | 2 +- .../lib/fg_http_web/controllers/device_controller.ex | 2 +- .../lib/fg_http_web/controllers/rule_controller.ex | 10 +++++++--- .../lib/fg_http_web/templates/rule/edit.html.eex | 2 +- .../lib/fg_http_web/templates/rule/index.html.eex | 4 ++++ .../lib/fg_http_web/templates/rule/show.html.eex | 12 +++++++++++- 8 files changed, 30 insertions(+), 10 deletions(-) diff --git a/apps/fg_http/lib/fg_http/devices.ex b/apps/fg_http/lib/fg_http/devices.ex index 65d0367af..bc8fa3944 100644 --- a/apps/fg_http/lib/fg_http/devices.ex +++ b/apps/fg_http/lib/fg_http/devices.ex @@ -17,8 +17,10 @@ defmodule FgHttp.Devices do [%Device{}, ...] """ - def list_devices do - Repo.all(Device) + def list_devices, do: Repo.all(Device) + + def list_devices(user_id) do + Repo.all(from d in Device, where: d.user_id == ^user_id) end @doc """ diff --git a/apps/fg_http/lib/fg_http/devices/device.ex b/apps/fg_http/lib/fg_http/devices/device.ex index a06ba621e..794575654 100644 --- a/apps/fg_http/lib/fg_http/devices/device.ex +++ b/apps/fg_http/lib/fg_http/devices/device.ex @@ -11,7 +11,7 @@ defmodule FgHttp.Devices.Device do schema "devices" do field :name, :string field :public_key, :string - field :last_ip, :map + field :last_ip, EctoNetwork.INET has_many :rules, Rule belongs_to :user, User diff --git a/apps/fg_http/lib/fg_http/rules.ex b/apps/fg_http/lib/fg_http/rules.ex index 78f142f62..fd426adae 100644 --- a/apps/fg_http/lib/fg_http/rules.ex +++ b/apps/fg_http/lib/fg_http/rules.ex @@ -18,7 +18,7 @@ defmodule FgHttp.Rules do """ def list_rules(device_id) do - Repo.all(from r in Rule, where: r.device_id == ^device_id, select: "*") + Repo.all(from r in Rule, where: r.device_id == ^device_id) end def list_rules do diff --git a/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex b/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex index 6fe3802ba..97aab5114 100644 --- a/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex +++ b/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex @@ -9,7 +9,7 @@ defmodule FgHttpWeb.DeviceController do plug FgHttpWeb.Plugs.Authenticator def index(conn, _params) do - devices = Devices.list_devices() + devices = Devices.list_devices(conn.assigns.current_user.id) render(conn, "index.html", devices: devices) 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 3d53ed9d2..8ad21d26c 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 @@ -20,15 +20,19 @@ defmodule FgHttpWeb.RuleController do render(conn, "new.html", changeset: changeset, device: device) end - def create(conn, %{"rule" => rule_params}) do - case Rules.create_rule(rule_params) do + def create(conn, %{"device_id" => device_id, "rule" => rule_params}) do + # XXX RBAC + all_params = Map.merge(rule_params, %{"device_id" => device_id}) + + case Rules.create_rule(all_params) do {:ok, rule} -> conn |> put_flash(:info, "Rule created successfully.") |> redirect(to: Routes.rule_path(conn, :show, rule)) {:error, %Ecto.Changeset{} = changeset} -> - render(conn, "new.html", changeset: changeset) + device = Devices.get_device!(device_id) + render(conn, "new.html", device: device, changeset: changeset) end end diff --git a/apps/fg_http/lib/fg_http_web/templates/rule/edit.html.eex b/apps/fg_http/lib/fg_http_web/templates/rule/edit.html.eex index e49613818..473e03412 100644 --- a/apps/fg_http/lib/fg_http_web/templates/rule/edit.html.eex +++ b/apps/fg_http/lib/fg_http_web/templates/rule/edit.html.eex @@ -2,4 +2,4 @@ <%= render "form.html", Map.put(assigns, :action, Routes.rule_path(@conn, :update, @rule)) %> -<%= link "Back", to: Routes.rule_path(@conn, :index, @rule.device) %> +<%= link "Back", to: Routes.device_rule_path(@conn, :index, @rule.device_id) %> 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 a38306450..6624cef3a 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 @@ -3,18 +3,22 @@ + + <%= for rule <- @rules do %> + +
Action Destination Port ProtocolPriority Enabled
<%= rule.action %> <%= rule.destination %> <%= rule.port %> <%= rule.protocol %><%= rule.priority %> <%= rule.enabled %> diff --git a/apps/fg_http/lib/fg_http_web/templates/rule/show.html.eex b/apps/fg_http/lib/fg_http_web/templates/rule/show.html.eex index 6c785c6bb..90198176b 100644 --- a/apps/fg_http/lib/fg_http_web/templates/rule/show.html.eex +++ b/apps/fg_http/lib/fg_http_web/templates/rule/show.html.eex @@ -2,6 +2,11 @@
    +
  • + Action: + <%= @rule.action %> +
  • +
  • Destination: <%= @rule.destination %> @@ -17,6 +22,11 @@ <%= @rule.protocol %>
  • +
  • + Priority + <%= @rule.priority %> +
  • +
  • Enabled: <%= @rule.enabled %> @@ -25,4 +35,4 @@
<%= link "Edit", to: Routes.rule_path(@conn, :edit, @rule) %> -<%= link "Back", to: Routes.rule_path(@conn, :index, @rule.device) %> +<%= link "Back", to: Routes.device_rule_path(@conn, :index, @rule.device_id) %> From 78fbb40eda2e490da45f1eca48cbae214eecfe06 Mon Sep 17 00:00:00 2001 From: Jamil Bou Kheir Date: Fri, 15 May 2020 00:46:43 -0500 Subject: [PATCH 4/4] Need to mock auth --- .../test/fg_http_web/controllers/device_controller_test.exs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/fg_http/test/fg_http_web/controllers/device_controller_test.exs b/apps/fg_http/test/fg_http_web/controllers/device_controller_test.exs index 0b5f37b0e..351710262 100644 --- a/apps/fg_http/test/fg_http_web/controllers/device_controller_test.exs +++ b/apps/fg_http/test/fg_http_web/controllers/device_controller_test.exs @@ -20,6 +20,9 @@ defmodule FgHttpWeb.DeviceControllerTest do describe "index" do test "lists all devices", %{conn: conn} do + # Mock authentication + conn = Plug.Conn.assign(conn, :current_user, fixture(:user)) + conn = get(conn, Routes.device_path(conn, :index)) assert html_response(conn, 200) =~ "Listing Devices" end