This commit is contained in:
byte[] 2019-11-15 19:40:32 -05:00
parent 54fd5f3c47
commit ab5b7782c7
7 changed files with 126 additions and 2 deletions

View file

@ -293,4 +293,57 @@ defmodule Philomena.Bans do
def change_user(%User{} = user) do
User.changeset(user, %{})
end
@doc """
Returns the first ban, if any, that matches the specified request
attributes.
"""
def exists_for?(user, ip, fingerprint) do
now = DateTime.utc_now()
queries =
subnet_query(ip, now) ++
fingerprint_query(fingerprint, now) ++
user_query(user, now)
union_all_queries(queries)
|> limit(1)
|> Repo.one()
end
defp fingerprint_query(nil, _now), do: []
defp fingerprint_query(fingerprint, now) do
[
Fingerprint
|> select([:id, :reason, :valid_until])
|> where([f], f.enabled and f.valid_until > ^now)
|> where([f], f.fingerprint == ^fingerprint)
]
end
defp subnet_query(nil, _now), do: []
defp subnet_query(ip, now) do
{:ok, inet} = EctoNetwork.INET.cast(ip)
[
Subnet
|> select([:id, :reason, :valid_until])
|> where([s], s.enabled and s.valid_until > ^now)
|> where(fragment("specification >>= ?", ^inet))
]
end
defp user_query(nil, _now), do: []
defp user_query(user, now) do
[
User
|> select([:id, :reason, :valid_until])
|> where([u], u.enabled and u.valid_until > ^now)
|> where([u], u.user_id == ^user.id)
]
end
defp union_all_queries([query]),
do: query
defp union_all_queries([query | rest]),
do: query |> union_all(^union_all_queries(rest))
end

View file

@ -5,6 +5,9 @@ defmodule PhilomenaWeb.Endpoint do
websocket: true,
longpoll: false
# Overwrite remote_ip based on X-Forwarded-For
plug RemoteIp
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phx.digest
@ -48,6 +51,6 @@ defmodule PhilomenaWeb.Endpoint do
plug PhilomenaWeb.Plugs.ReloadUser
plug PhilomenaWeb.Plugs.RenderTime
plug PhilomenaWeb.Plugs.CurrentFilter
plug PhilomenaWeb.Plugs.Referrer
plug PhilomenaWeb.Router
end

View file

@ -0,0 +1,32 @@
defmodule PhilomenaWeb.Plugs.CurrentBan do
@moduledoc """
This plug loads the ban for the current user.
## Example
plug PhilomenaWeb.Plugs.Ban
"""
alias Philomena.Bans
alias Plug.Conn
alias Pow.Plug
@doc false
@spec init(any()) :: any()
def init(opts), do: opts
@doc false
@spec call(Conn.t(), any()) :: Conn.t()
def call(conn, _opts) do
conn =
conn
|> Conn.fetch_cookies()
fingerprint = conn.cookies["_ses"]
user = Plug.current_user(conn)
ip = conn.remote_ip
ban = Bans.exists_for?(user, ip, fingerprint)
Conn.assign(conn, :current_ban, ban)
end
end

View file

@ -0,0 +1,30 @@
defmodule PhilomenaWeb.Plugs.Referrer do
@moduledoc """
This plug assigns the HTTP Referer, if it exists. Note the misspelling
in the standard.
## Example
plug PhilomenaWeb.Plugs.Referrer
"""
alias Plug.Conn
@doc false
@spec init(any()) :: any()
def init(opts), do: opts
@doc false
@spec call(Conn.t(), any()) :: Conn.t()
def call(conn, _opts) do
case Conn.get_req_header(conn, "referer") do
[] ->
conn
|> Conn.assign(:referrer, "/")
[referrer] ->
conn
|> Conn.assign(:referrer, referrer)
end
end
end

View file

@ -9,9 +9,11 @@ defmodule PhilomenaWeb.Router do
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug PhilomenaWeb.Plugs.CurrentFilter
plug PhilomenaWeb.Plugs.ImageFilter
plug PhilomenaWeb.Plugs.Pagination
plug PhilomenaWeb.Plugs.EnsureUserEnabledPlug
plug PhilomenaWeb.Plugs.CurrentBan
end
pipeline :api do

View file

@ -57,7 +57,8 @@ defmodule Philomena.MixProject do
{:qrcode, "~> 0.1.5"},
{:redix, "~> 0.10.2"},
{:bamboo, "~> 1.2"},
{:bamboo_smtp, "~> 1.7"}
{:bamboo_smtp, "~> 1.7"},
{:remote_ip, "~> 0.1.5"}
]
end

View file

@ -5,6 +5,7 @@
"canada": {:hex, :canada, "1.0.2", "040e4c47609b0a67d5773ac1fbe5e99f840cef173d69b739beda7c98453e0770", [:mix], [], "hexpm"},
"canary": {:hex, :canary, "1.1.1", "4138d5e05db8497c477e4af73902eb9ae06e49dceaa13c2dd9f0b55525ded48b", [:mix], [{:canada, "~> 1.0.1", [hex: :canada, repo: "hexpm", optional: false]}, {:ecto, ">= 1.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm"},
"comeonin": {:hex, :comeonin, "5.1.2", "fbbbbbfcf0f0e9900c0336d16c8d462edf838ba1759577e29cc5fbd7c28a4540", [:mix], [], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
@ -23,6 +24,7 @@
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "1.6.0", "0a148c836e8e5fbec82c3cea37465a603bd42e314b73a8448ad50020757a00bd", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
@ -47,6 +49,7 @@
"qrcode": {:hex, :qrcode, "0.1.5", "551271830515c150f34568345b060c625deb0e6691db2a01b0a6de3aafc93886", [:mix], [], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"redix": {:hex, :redix, "0.10.2", "a9eabf47898aa878650df36194aeb63966d74f5bd69d9caa37babb32dbb93c5d", [:mix], [{:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"remote_ip": {:hex, :remote_ip, "0.1.5", "0d8eb8a80387e196b0f48b3e7efb75525d1097cdb0ec70a4c69dd2ce9237c16c", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:inet_cidr, "~> 1.0", [hex: :inet_cidr, repo: "hexpm", optional: false]}, {:plug, "~> 1.2", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"retry": {:hex, :retry, "0.13.0", "bb9b2713f70f39337837852337ad280c77662574f4fb852a8386c269f3d734c4", [:mix], [], "hexpm"},
"scrivener": {:hex, :scrivener, "2.7.0", "fa94cdea21fad0649921d8066b1833d18d296217bfdf4a5389a2f45ee857b773", [:mix], [], "hexpm"},
"scrivener_ecto": {:hex, :scrivener_ecto, "2.2.0", "53d5f1ba28f35f17891cf526ee102f8f225b7024d1cdaf8984875467158c9c5e", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm"},