From 0d8e1c5ceb47c0fe7b276c1b0e8e9d02eb4e473f Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Fri, 20 Dec 2019 13:58:06 -0500 Subject: [PATCH] auto ip bans --- lib/philomena/bans.ex | 37 +++++++++++++++++-- .../controllers/admin/user_ban_controller.ex | 2 +- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/philomena/bans.ex b/lib/philomena/bans.ex index ec6d7e05..af534ac1 100644 --- a/lib/philomena/bans.ex +++ b/lib/philomena/bans.ex @@ -4,8 +4,10 @@ defmodule Philomena.Bans do """ import Ecto.Query, warn: false + alias Ecto.Multi alias Philomena.Repo + alias Philomena.UserIps.UserIp alias Philomena.Bans.Fingerprint @doc """ @@ -242,11 +244,40 @@ defmodule Philomena.Bans do """ def create_user(creator, attrs \\ %{}) do - %User{banning_user_id: creator.id} - |> User.save_changeset(attrs) - |> Repo.insert() + user_ban = + %User{banning_user_id: creator.id} + |> User.save_changeset(attrs) + + Multi.new() + |> Multi.insert(:user_ban, user_ban) + |> Multi.run(:auto_ip_ban, fn repo, %{user_ban: user_ban} -> + UserIp + |> where(user_id: ^user_ban.user_id) + |> order_by(desc: :updated_at) + |> limit(1) + |> select([u], u.ip) + |> Repo.one() + |> case do + nil -> + {:ok, nil} + + ip -> + ip = masked_ip(ip) + + %Subnet{banning_user_id: creator.id, specification: ip} + |> Subnet.save_changeset(attrs) + |> repo.insert() + end + end) + |> Repo.isolated_transaction(:serializable) end + defp masked_ip(%Postgrex.INET{address: {_1, _2, _3, _4}} = ip), + do: ip + + defp masked_ip(%Postgrex.INET{address: {h1, h2, h3, h4, _5, _6, _7, _8}} = ip), + do: %{ip | address: {h1, h2, h3, h4, 0, 0, 0, 0}, netmask: 64} + @doc """ Updates a user. diff --git a/lib/philomena_web/controllers/admin/user_ban_controller.ex b/lib/philomena_web/controllers/admin/user_ban_controller.ex index 862bf839..7a9ed264 100644 --- a/lib/philomena_web/controllers/admin/user_ban_controller.ex +++ b/lib/philomena_web/controllers/admin/user_ban_controller.ex @@ -50,7 +50,7 @@ defmodule PhilomenaWeb.Admin.UserBanController do |> put_flash(:info, "User was successfully banned.") |> redirect(to: Routes.admin_user_ban_path(conn, :index)) - {:error, changeset} -> + {:error, :user_ban, changeset, _changes} -> render(conn, "new.html", changeset: changeset) end end