styling, require a code for prompts, admin privs, ordering, filtering, jump-to-page
This commit is contained in:
67
lib/diffuser_web/plugs/public_ip.ex
Normal file
67
lib/diffuser_web/plugs/public_ip.ex
Normal file
@@ -0,0 +1,67 @@
|
||||
defmodule DiffuserWeb.Plugs.PublicIp do
|
||||
@moduledoc "Get public IP address of request from x-forwarded-for header"
|
||||
|
||||
def init(opts), do: opts
|
||||
|
||||
def call(%{assigns: %{ip: _}} = conn, _opts), do: conn
|
||||
|
||||
def call(conn, _opts) do
|
||||
process(conn, Plug.Conn.get_req_header(conn, "x-forwarded-for"))
|
||||
end
|
||||
|
||||
def process(%{remote_ip: remote_ip} = conn, []) do
|
||||
Plug.Conn.assign(conn, :ip, to_string(:inet_parse.ntoa(remote_ip)))
|
||||
end
|
||||
|
||||
def process(conn, vals) do
|
||||
# Rewrite standard remote_ip field with value from header
|
||||
ip_address = get_ip_address(conn, vals)
|
||||
# See https://hexdocs.pm/plug/Plug.Conn.html
|
||||
conn = %{conn | remote_ip: ip_address}
|
||||
|
||||
Plug.Conn.assign(conn, :ip, to_string(:inet_parse.ntoa(ip_address)))
|
||||
end
|
||||
|
||||
defp get_ip_address(conn, vals)
|
||||
defp get_ip_address(%{remote_ip: remote_ip}, []), do: remote_ip
|
||||
|
||||
defp get_ip_address(%{remote_ip: remote_ip} = _conn, [val | _]) do
|
||||
# Split into multiple values
|
||||
comps =
|
||||
val
|
||||
|> String.split(~r{\s*,\s*}, trim: true)
|
||||
# Get rid of "unknown" values
|
||||
|> Enum.filter(&(&1 != "unknown"))
|
||||
# Split IP from port, if any
|
||||
|> Enum.map(&hd(String.split(&1, ":")))
|
||||
# Filter out blanks
|
||||
|> Enum.filter(&(&1 != ""))
|
||||
# Parse address into :inet.ip_address tuple
|
||||
|> Enum.map(&parse_address(&1))
|
||||
# Elminate internal IP addreses, e.g. 192.168.1.1
|
||||
|> Enum.filter(&is_public_ip(&1))
|
||||
|
||||
case comps do
|
||||
[] -> remote_ip
|
||||
[comp | _] -> comp
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_address(ip) do
|
||||
case :inet.parse_ipv4strict_address(to_charlist(ip)) do
|
||||
{:ok, ip_address} -> ip_address
|
||||
{:error, :einval} -> :einval
|
||||
end
|
||||
end
|
||||
|
||||
defp is_public_ip(ip_address) do
|
||||
case ip_address do
|
||||
{10, _, _, _} -> false
|
||||
{192, 168, _, _} -> false
|
||||
{172, second, _, _} when second >= 16 and second <= 31 -> false
|
||||
{127, 0, 0, _} -> false
|
||||
{_, _, _, _} -> true
|
||||
:einval -> false
|
||||
end
|
||||
end
|
||||
end
|
37
lib/diffuser_web/plugs/user_auth.ex
Normal file
37
lib/diffuser_web/plugs/user_auth.ex
Normal file
@@ -0,0 +1,37 @@
|
||||
defmodule DiffuserWeb.Plugs.UserAuth do
|
||||
use DiffuserWeb, :controller
|
||||
import Plug.Conn
|
||||
alias Diffuser.Accounts
|
||||
alias Diffuser.Repo
|
||||
|
||||
def init(default), do: default
|
||||
|
||||
def call(%{remote_ip: remote_ip} = conn, _) do
|
||||
remote_ip = remote_ip |> :inet_parse.ntoa() |> to_string()
|
||||
|
||||
case get_session(conn, :user) do
|
||||
nil ->
|
||||
with {:ok, user} <- Accounts.create_user(%{ip_address: remote_ip}) do
|
||||
put_session(conn, :user, user |> Repo.preload(votes: [:prompt_request]))
|
||||
else
|
||||
{:error, _changeset} -> put_session(conn, :user, nil)
|
||||
end
|
||||
|
||||
%Accounts.User{ip_address: user_ip} = user ->
|
||||
with false <- user_ip == remote_ip,
|
||||
{:ok, user} <- Accounts.update_user(user, %{ip_address: remote_ip}) do
|
||||
conn |> put_session(:user, user |> Repo.preload(votes: [:prompt_request]))
|
||||
else
|
||||
true ->
|
||||
put_session(
|
||||
conn,
|
||||
:user,
|
||||
Accounts.get_user!(user.id) |> Repo.preload(votes: [:prompt_request])
|
||||
)
|
||||
|
||||
_ ->
|
||||
put_session(conn, :user, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
16
lib/diffuser_web/plugs/validate_admin.ex
Normal file
16
lib/diffuser_web/plugs/validate_admin.ex
Normal file
@@ -0,0 +1,16 @@
|
||||
defmodule DiffuserWeb.Plugs.ValidateAdmin do
|
||||
use DiffuserWeb, :controller
|
||||
import Plug.Conn
|
||||
|
||||
def init(default), do: default
|
||||
|
||||
def call(%{remote_ip: remote_ip} = conn, _) do
|
||||
remote_ip = remote_ip |> :inet_parse.ntoa() |> to_string()
|
||||
|
||||
if remote_ip == "127.0.0.1" do
|
||||
conn |> put_session(:is_admin, true)
|
||||
else
|
||||
conn |> put_session(:is_admin, false)
|
||||
end
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user