From 3818a0e0d14ca7198aaa9b3bc6f24a4cb148d805 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Tue, 17 Dec 2019 20:35:07 -0500 Subject: [PATCH] automatic user link verifier --- lib/philomena/application.ex | 1 + lib/philomena/servers/user_link_updater.ex | 79 ++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 lib/philomena/servers/user_link_updater.ex diff --git a/lib/philomena/application.ex b/lib/philomena/application.ex index e7dfca72..cb59ae33 100644 --- a/lib/philomena/application.ex +++ b/lib/philomena/application.ex @@ -15,6 +15,7 @@ defmodule Philomena.Application do # Starts a worker by calling: Philomena.Worker.start_link(arg) # {Philomena.Worker, arg}, Philomena.Servers.ImageProcessor, + Philomena.Servers.UserLinkUpdater, Pow.Store.Backend.MnesiaCache, {Redix, name: :redix, host: Application.get_env(:philomena, :redis_host)} ] diff --git a/lib/philomena/servers/user_link_updater.ex b/lib/philomena/servers/user_link_updater.ex new file mode 100644 index 00000000..4d33e0a8 --- /dev/null +++ b/lib/philomena/servers/user_link_updater.ex @@ -0,0 +1,79 @@ +defmodule Philomena.Servers.UserLinkUpdater do + alias Philomena.UserLinks.UserLink + alias Philomena.Repo + import Ecto.Query + + @seven_days 7*24*60*60 + @three_days 3*24*60*60 + @twelve_hours 12*60*60 + @one_hour 60*60 + @two_minutes 2*60 + + def child_spec([]) do + %{ + id: Philomena.Servers.UserLinkUpdater, + start: {Philomena.Servers.UserLinkUpdater, :start_link, [[]]} + } + end + + def start_link([]) do + {:ok, spawn_link(&run/0)} + end + + defp run do + now = DateTime.utc_now() + + UserLink + |> where([ul], ul.aasm_state == "unverified" and ul.next_check_at < ^now) + |> Repo.all(log: false) + |> Enum.map(&automatic_verify/1) + + :timer.sleep(:timer.seconds(120)) + run() + end + + defp automatic_verify(user_link) do + now = DateTime.utc_now() |> DateTime.truncate(:second) + diff = DateTime.diff(now, user_link.created_at, :second) + + # Set next check time according to how long link has been pending + + next_check_at = + cond do + diff > @seven_days -> + DateTime.add(now, @seven_days) + + diff > @three_days -> + DateTime.add(now, @twelve_hours) + + diff > @one_hour -> + DateTime.add(now, @one_hour) + + true -> + DateTime.add(now, @two_minutes) + end + + UserLink + |> where(id: ^user_link.id) + |> Repo.update_all(set: [next_check_at: next_check_at]) + + user_link + |> Map.get(:uri) + |> Philomena.Http.get!() + |> handle_response(user_link) + end + + defp handle_response(%HTTPoison.Response{body: body, status_code: 200}, user_link) do + case :binary.match(body, user_link.verification_code) do + :nomatch -> + nil + + _match -> + UserLink + |> where(id: ^user_link.id) + |> Repo.update_all(set: [next_check_at: nil, aasm_state: "link_verified"]) + end + end + + defp handle_response(_, _user_link), do: nil +end