defmodule MicrowavepropWeb.Router do use MicrowavepropWeb, :router import MicrowavepropWeb.UserAuth import Oban.Web.Router import Phoenix.LiveDashboard.Router pipeline :browser do plug :accepts, ["html"] plug :fetch_session plug :store_remote_ip plug :store_cf_geo plug :fetch_live_flash plug :put_root_layout, html: {MicrowavepropWeb.Layouts, :root} plug :protect_from_forgery plug :put_secure_browser_headers plug :fetch_current_scope_for_user end defp store_remote_ip(conn, _opts) do ip_str = conn.remote_ip |> :inet.ntoa() |> to_string() Plug.Conn.put_session(conn, :remote_ip, ip_str) end # Extract Cloudflare visitor geolocation headers (set by a Cloudflare # Managed Transform) and stash them in the session so LiveViews can use # them to center maps on the visitor's approximate location. defp store_cf_geo(conn, _opts) do lat = conn |> Plug.Conn.get_req_header("cf-iplatitude") |> List.first() lon = conn |> Plug.Conn.get_req_header("cf-iplongitude") |> List.first() with {lat_f, ""} when is_float(lat_f) <- lat && Float.parse(lat), {lon_f, ""} when is_float(lon_f) <- lon && Float.parse(lon) do conn |> Plug.Conn.put_session(:cf_lat, lat_f) |> Plug.Conn.put_session(:cf_lon, lon_f) else _ -> conn end end pipeline :api do plug :accepts, ["json"] end # Health check — no pipeline, minimal overhead get "/health", MicrowavepropWeb.HealthController, :check, log: false # Admin-only routes must come first so that literal segments like # `/beacons/:id/edit` are registered before the public `/beacons/:id`. scope "/", MicrowavepropWeb do pipe_through [:browser, :require_authenticated_user] live_session :admin, on_mount: [{MicrowavepropWeb.UserAuth, :require_admin}] do live "/beacons/:id/edit", BeaconLive.Form, :edit live "/admin/backfill", BackfillLive live "/admin/contact-edits", Admin.ContactEditLive live "/users", UserManagementLive.Index, :index live "/users/:id/edit", UserManagementLive.Edit, :edit end end scope "/", MicrowavepropWeb do pipe_through :browser get "/", PageController, :home live_session :public, on_mount: [{MicrowavepropWeb.UserAuth, :default}] do live "/submit", SubmitLive live "/map", MapLive live "/weather", WeatherMapLive live "/contacts", ContactLive.Index live "/contacts/map", ContactMapLive live "/contacts/:id", ContactLive.Show live "/path", PathLive live "/rover", RoverLive live "/algo", AlgoLive live "/about", AboutLive live "/privacy", PrivacyLive # Beacons: public read + submit (pending admin approval) live "/beacons", BeaconLive.Index, :index live "/beacons/new", BeaconLive.Form, :new live "/beacons/:id", BeaconLive.Show, :show end # Redirect old /qsos routes get "/qsos", PageController, :redirect_contacts get "/qsos/:id", PageController, :redirect_contact end # Other scopes may use custom stacks. # scope "/api", MicrowavepropWeb do # pipe_through :api # end scope "/" do pipe_through [:browser, :require_authenticated_user] live_dashboard "/admin/dashboard", metrics: MicrowavepropWeb.Telemetry, ecto_repos: [Microwaveprop.Repo], ecto_psql_extras_options: [long_running_queries: [threshold: "200 milliseconds"]], on_mount: [{MicrowavepropWeb.UserAuth, :require_admin}] oban_dashboard("/admin/oban", on_mount: [{MicrowavepropWeb.UserAuth, :require_admin}]) end # Enable Swoosh mailbox preview in development if Application.compile_env(:microwaveprop, :dev_routes) do scope "/dev" do pipe_through :browser forward "/mailbox", Plug.Swoosh.MailboxPreview end end ## Authentication routes scope "/", MicrowavepropWeb do pipe_through [:browser, :redirect_if_user_is_authenticated] get "/users/register", UserRegistrationController, :new post "/users/register", UserRegistrationController, :create end scope "/", MicrowavepropWeb do pipe_through [:browser, :require_authenticated_user] get "/users/settings", UserSettingsController, :edit put "/users/settings", UserSettingsController, :update get "/users/settings/confirm-email/:token", UserSettingsController, :confirm_email post "/users/beacon-monitors", BeaconMonitorController, :create delete "/users/beacon-monitors/:id", BeaconMonitorController, :delete end scope "/", MicrowavepropWeb do pipe_through [:browser] get "/users/log-in", UserSessionController, :new get "/users/confirm/:token", UserSessionController, :confirm post "/users/log-in", UserSessionController, :create delete "/users/log-out", UserSessionController, :delete end end