mirror of
https://github.com/plausible/analytics.git
synced 2024-12-26 11:02:52 +03:00
97b24c0492
* Add SSO link with signed JWT token * Falls back to Nolt URL without SSO if token cannot be generated * Add profile image (gravatar) to Nolt SSO link * Improve navbar dropdown * Add 'contact support' link to nav dropdown * Add CSS rule to prevent horizontal jumps * Dark mode styling * Close dropdown when link is clicked * Clarify links in dropdown * Clarify CSS comment * Use Alpine.data() over window * Rename suggestions_dropdown -> combo-box * Mix format * Make logout link look good on dark mode * Use proxy for gravatar * Do not use Gravatar proxy in self-hosted * Changelog * Add Github Repo link to nav dropdown * Make dialyzer happy * Add proxy for Gravatar * Update assets/css/app.css Co-authored-by: hq1 <hq@mtod.org> * Update lib/plausible_web/controllers/avatar_controller.ex Co-authored-by: hq1 <hq@mtod.org> * Fix alpine <> Liveview integration --------- Co-authored-by: hq1 <hq@mtod.org>
39 lines
1.5 KiB
Elixir
39 lines
1.5 KiB
Elixir
defmodule PlausibleWeb.AvatarController do
|
|
@moduledoc """
|
|
This module proxies requests to BASE_URL/avatar/:hash to www.gravatar.com/avatar/:hash.
|
|
|
|
The purpose is to make use of Gravatar's convenient avatar service without exposing information
|
|
that could be used for tracking the Plausible user. Compared to requesting the Gravatar directly
|
|
from the browser, this proxy module protects the Plausible user from disclosing to Gravatar:
|
|
1. The client IP address
|
|
2. User-Agent
|
|
3. Referer header which can be used to track which site the user is visiting (i.e. plausible.io or self-hosted URL)
|
|
|
|
The downside is the added latency from the request having to go through the Plausible server, rather than contacting the
|
|
local CDN server operated by Gravatar's service.
|
|
"""
|
|
use PlausibleWeb, :controller
|
|
alias Plausible.HTTPClient
|
|
|
|
@gravatar_base_url "https://www.gravatar.com"
|
|
def avatar(conn, params) do
|
|
url = Path.join(@gravatar_base_url, ["avatar/", params["hash"]]) <> "?s=150&d=identicon"
|
|
|
|
case HTTPClient.impl().get(url) do
|
|
{:ok, %Finch.Response{status: 200, body: body, headers: headers}} ->
|
|
conn
|
|
|> forward_headers(headers)
|
|
|> send_resp(200, body)
|
|
|
|
{:error, _} ->
|
|
send_resp(conn, 400, "")
|
|
end
|
|
end
|
|
|
|
@forwarded_headers ["content-type", "cache-control", "expires"]
|
|
defp forward_headers(conn, headers) do
|
|
headers_to_forward = Enum.filter(headers, fn {k, _} -> k in @forwarded_headers end)
|
|
%Plug.Conn{conn | resp_headers: headers_to_forward}
|
|
end
|
|
end
|