From ac1dab0fc017f418f3091d8900b2cd28a35369b4 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Mon, 12 Aug 2019 17:41:41 +0200
Subject: [PATCH] Fix guardian db hook when refresh the access token

---
 config/test.exs                     |  2 +-
 lib/mobilizon/users/users.ex        | 12 ++++++++++--
 lib/mobilizon_web/guardian.ex       |  8 ++++++++
 lib/mobilizon_web/resolvers/user.ex | 23 +++++++++++++++++------
 lib/mobilizon_web/schema.ex         |  6 +++++-
 5 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/config/test.exs b/config/test.exs
index 21432393b..e31d9fbfb 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -19,7 +19,7 @@ config :mobilizon, MobilizonWeb.Endpoint,
 config :logger,
   backends: [:console],
   compile_time_purge_level: :debug,
-  level: :info
+  level: :debug
 
 # Configure your database
 config :mobilizon, Mobilizon.Repo,
diff --git a/lib/mobilizon/users/users.ex b/lib/mobilizon/users/users.ex
index 9fea52635..90d10de5d 100644
--- a/lib/mobilizon/users/users.ex
+++ b/lib/mobilizon/users/users.ex
@@ -253,13 +253,21 @@ defmodule Mobilizon.Users do
   end
 
   def generate_access_token(user) do
-    with {:ok, access_token, _claims} <- MobilizonWeb.Guardian.encode_and_sign(user, %{}, token_type: "access", ttl: {5, :seconds}) do
+    with {:ok, access_token, _claims} <-
+           MobilizonWeb.Guardian.encode_and_sign(user, %{},
+             token_type: "access",
+             ttl: {5, :seconds}
+           ) do
       {:ok, access_token}
     end
   end
 
   def generate_refresh_token(user) do
-    with {:ok, refresh_token, _claims} <- MobilizonWeb.Guardian.encode_and_sign(user, %{}, token_type: "refresh", ttl: {30, :days}) do
+    with {:ok, refresh_token, _claims} <-
+           MobilizonWeb.Guardian.encode_and_sign(user, %{},
+             token_type: "refresh",
+             ttl: {30, :days}
+           ) do
       {:ok, refresh_token}
     end
   end
diff --git a/lib/mobilizon_web/guardian.ex b/lib/mobilizon_web/guardian.ex
index 465178f1b..8fd954c6d 100644
--- a/lib/mobilizon_web/guardian.ex
+++ b/lib/mobilizon_web/guardian.ex
@@ -61,6 +61,14 @@ defmodule MobilizonWeb.Guardian do
     end
   end
 
+  def on_refresh({old_token, old_claims}, {new_token, new_claims}, _options) do
+    with {:ok, _, _} <- Guardian.DB.on_refresh({old_token, old_claims}, {new_token, new_claims}) do
+      {:ok, {old_token, old_claims}, {new_token, new_claims}}
+    end
+  end
+
+  def on_exchange(old_stuff, new_stuff, options), do: on_refresh(old_stuff, new_stuff, options)
+
   #  def build_claims(claims, _resource, opts) do
   #    claims = claims
   #             |> encode_permissions_into_claims!(Keyword.get(opts, :permissions))
diff --git a/lib/mobilizon_web/resolvers/user.ex b/lib/mobilizon_web/resolvers/user.ex
index 6cbf5d456..ef3f0839f 100644
--- a/lib/mobilizon_web/resolvers/user.ex
+++ b/lib/mobilizon_web/resolvers/user.ex
@@ -65,7 +65,8 @@ defmodule MobilizonWeb.Resolvers.User do
   """
   def login_user(_parent, %{email: email, password: password}, _resolution) do
     with {:ok, %User{} = user} <- Users.get_user_by_email(email, true),
-         {:ok, %{access_token: access_token, refresh_token: refresh_token}} <- Users.authenticate(%{user: user, password: password}) do
+         {:ok, %{access_token: access_token, refresh_token: refresh_token}} <-
+           Users.authenticate(%{user: user, password: password}) do
       {:ok, %{access_token: access_token, refresh_token: refresh_token, user: user}}
     else
       {:error, :user_not_found} ->
@@ -86,8 +87,11 @@ defmodule MobilizonWeb.Resolvers.User do
         },
         _context
       ) do
-    with {:ok, _old, {exchanged_token, _claims}} <- MobilizonWeb.Guardian.exchange(refresh_token, "refresh", "access", ttl: { 1, :days}),
-         {:ok, user, _claims} <- MobilizonWeb.Guardian.resource_from_token(refresh_token),
+    with {:ok, user, _claims} <- MobilizonWeb.Guardian.resource_from_token(refresh_token),
+         {:ok, _old, {exchanged_token, _claims}} <-
+           MobilizonWeb.Guardian.exchange(refresh_token, ["access", "refresh"], "access",
+             ttl: {1, :days}
+           ),
          {:ok, refresh_token} <- Users.generate_refresh_token(user) do
       {:ok, %{access_token: exchanged_token, refresh_token: refresh_token}}
     else
@@ -128,8 +132,14 @@ defmodule MobilizonWeb.Resolvers.User do
     with {:check_confirmation_token, {:ok, %User{} = user}} <-
            {:check_confirmation_token, Activation.check_confirmation_token(token)},
          {:get_actor, actor} <- {:get_actor, Users.get_actor_for_user(user)},
-         {:ok, %{access_token: access_token, refresh_token: refresh_token}} <- Users.generate_tokens(user) do
-      {:ok, %{access_token: access_token, refresh_token: refresh_token, user: Map.put(user, :default_actor, actor)}}
+         {:ok, %{access_token: access_token, refresh_token: refresh_token}} <-
+           Users.generate_tokens(user) do
+      {:ok,
+       %{
+         access_token: access_token,
+         refresh_token: refresh_token,
+         user: Map.put(user, :default_actor, actor)
+       }}
     else
       err ->
         Logger.info("Unable to validate user with token #{token}")
@@ -180,7 +190,8 @@ defmodule MobilizonWeb.Resolvers.User do
   def reset_password(_parent, %{password: password, token: token}, _resolution) do
     with {:ok, %User{} = user} <-
            ResetPassword.check_reset_password_token(password, token),
-         {:ok, %{access_token: access_token, refresh_token: refresh_token}} <- Users.authenticate(%{user: user, password: password}) do
+         {:ok, %{access_token: access_token, refresh_token: refresh_token}} <-
+           Users.authenticate(%{user: user, password: password}) do
       {:ok, %{access_token: access_token, refresh_token: refresh_token, user: user}}
     end
   end
diff --git a/lib/mobilizon_web/schema.ex b/lib/mobilizon_web/schema.ex
index 12cf95c3d..c3819ab75 100644
--- a/lib/mobilizon_web/schema.ex
+++ b/lib/mobilizon_web/schema.ex
@@ -32,7 +32,11 @@ defmodule MobilizonWeb.Schema do
   @desc "A JWT and the associated user ID"
   object :login do
     field(:access_token, non_null(:string), description: "A JWT Token for this session")
-    field(:refresh_token, non_null(:string), description: "A JWT Token to refresh the access token")
+
+    field(:refresh_token, non_null(:string),
+      description: "A JWT Token to refresh the access token"
+    )
+
     field(:user, non_null(:user), description: "The user associated to this session")
   end