Removes unreachable catch-all clauses, drops unused `require Logger` lines, adds pin operators to bitstring size patterns, reorders function heads for correct dispatch, and replaces deprecated LoggerBackends calls.
80 lines
2.1 KiB
Elixir
80 lines
2.1 KiB
Elixir
defmodule ToweropsWeb.Plugs.DetectEUUser do
|
|
@moduledoc """
|
|
Detects if a user is from an EU/EEA country that requires GDPR cookie consent.
|
|
|
|
Uses local GeoIP database to determine the user's country from their IP address.
|
|
|
|
The result is stored in conn.assigns.requires_cookie_consent
|
|
"""
|
|
import Plug.Conn
|
|
|
|
alias ToweropsWeb.RemoteIp
|
|
|
|
# EU/EEA country codes that require GDPR cookie consent
|
|
# EU member states + EEA countries (Norway, Iceland, Liechtenstein)
|
|
@eu_eea_countries ~w(
|
|
AT BE BG HR CY CZ DK EE FI FR DE GR HU IE IT LV LT LU MT NL PL PT RO SK SI ES SE
|
|
IS NO LI
|
|
)
|
|
|
|
# British overseas territories and Crown dependencies also covered by GDPR
|
|
@uk_territories ~w(
|
|
GB GG JE IM GI
|
|
)
|
|
|
|
@doc false
|
|
def init(opts), do: opts
|
|
|
|
@doc false
|
|
def call(conn, _opts) do
|
|
# Fetch cookies to check for existing consent
|
|
conn = fetch_cookies(conn)
|
|
requires_consent = detect_eu_user(conn)
|
|
|
|
conn
|
|
|> put_session(:requires_cookie_consent, requires_consent)
|
|
|> assign(:requires_cookie_consent, requires_consent)
|
|
end
|
|
|
|
defp detect_eu_user(conn) do
|
|
# If user has already accepted cookies, don't show banner
|
|
if has_consent_cookie?(conn) do
|
|
false
|
|
else
|
|
# In development (localhost), always show the banner for testing
|
|
hostname = conn.host
|
|
|
|
if hostname in ["localhost", "127.0.0.1"] do
|
|
true
|
|
else
|
|
detect_country_from_headers(conn)
|
|
end
|
|
end
|
|
end
|
|
|
|
defp has_consent_cookie?(conn) do
|
|
case conn.cookies["cookie_consent"] do
|
|
"accepted" -> true
|
|
_ -> false
|
|
end
|
|
end
|
|
|
|
defp detect_country_from_headers(conn) do
|
|
# Get remote IP from connection
|
|
remote_ip = RemoteIp.from_conn(conn) || "0.0.0.0"
|
|
|
|
case Towerops.GeoIP.lookup(remote_ip) do
|
|
country_code when is_binary(country_code) ->
|
|
eu_country?(country_code)
|
|
|
|
nil ->
|
|
# No country found - default to showing banner (conservative approach)
|
|
true
|
|
end
|
|
end
|
|
|
|
defp eu_country?(country_code) do
|
|
country_code = String.upcase(country_code)
|
|
country_code in @eu_eea_countries or country_code in @uk_territories
|
|
end
|
|
end
|