defmodule PhilomenaWeb.Profile.AliasController do use PhilomenaWeb, :controller alias Philomena.UserFingerprints.UserFingerprint alias Philomena.UserIps.UserIp alias Philomena.Users.User alias Philomena.Repo import Ecto.Query plug PhilomenaWeb.CanaryMapPlug, index: :show_details plug :load_and_authorize_resource, model: User, id_field: "slug", id_name: "profile_id", persisted: true def index(conn, _params) do user = conn.assigns.user # N.B.: subquery runs faster and is easier to read # than the equivalent join, but Ecto doesn't support # that for some reason (and ActiveRecord does??) ip_matches = User |> join(:inner, [u], _ in assoc(u, :user_ips)) |> join(:left, [u, ui1], ui2 in UserIp, on: ui1.ip == ui2.ip) |> where([u, _ui1, ui2], u.id != ^user.id and ui2.user_id == ^user.id) |> select([u, _ui1, _ui2], u) |> preload(:bans) |> Repo.all() |> Map.new(&{&1.id, &1}) fp_matches = User |> join(:inner, [u], _ in assoc(u, :user_fingerprints)) |> join(:left, [u, uf1], uf2 in UserFingerprint, on: uf1.fingerprint == uf2.fingerprint) |> where([u, _uf1, uf2], u.id != ^user.id and uf2.user_id == ^user.id) |> select([u, _uf1, _uf2], u) |> preload(:bans) |> Repo.all() |> Map.new(&{&1.id, &1}) both_matches = Map.take(ip_matches, Map.keys(fp_matches)) ip_matches = Map.drop(ip_matches, Map.keys(both_matches)) fp_matches = Map.drop(fp_matches, Map.keys(both_matches)) both_matches = Map.values(both_matches) ip_matches = Map.values(ip_matches) fp_matches = Map.values(fp_matches) render( conn, "index.html", title: "Potential Aliases for `#{user.name}'", both_matches: both_matches, ip_matches: ip_matches, fp_matches: fp_matches ) end end