reuse valid oauth tokens (#182)
[akkoma] / lib / pleroma / web / o_auth / token.ex
index 9170a7ec7daaf4fba673656f62d4e63d3da75a51..c9398aeaa2be645a6b31d14383cf1ad28ada18df 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.OAuth.Token do
@@ -27,6 +27,10 @@ defmodule Pleroma.Web.OAuth.Token do
     timestamps()
   end
 
+  def lifespan do
+    Pleroma.Config.get!([:oauth2, :token_expires_in])
+  end
+
   @doc "Gets token by unique access token"
   @spec get_by_token(String.t()) :: {:ok, t()} | {:error, :not_found}
   def get_by_token(token) do
@@ -66,6 +70,16 @@ defmodule Pleroma.Web.OAuth.Token do
     end
   end
 
+  def get_preeexisting_by_app_and_user(app, user) do
+    Query.get_by_app(app.id)
+    |> Query.get_by_user(user.id)
+    |> Query.get_unexpired()
+    |> Query.preload([:user])
+    |> Query.sort_by_inserted_at()
+    |> Query.limit(1)
+    |> Repo.find_resource()
+  end
+
   defp put_token(changeset) do
     changeset
     |> change(%{token: Token.Utils.generate_token()})
@@ -82,12 +96,20 @@ defmodule Pleroma.Web.OAuth.Token do
     |> unique_constraint(:refresh_token)
   end
 
+  def get_or_exchange_token(%Authorization{} = auth, %App{} = app, %User{} = user) do
+    if auth.used do
+      get_preeexisting_by_app_and_user(app, user)
+    else
+      exchange_token(app, auth)
+    end
+  end
+
   defp put_valid_until(changeset, attrs) do
-    expires_in =
-      Map.get(attrs, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), expires_in()))
+    valid_until =
+      Map.get(attrs, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), lifespan()))
 
     changeset
-    |> change(%{valid_until: expires_in})
+    |> change(%{valid_until: valid_until})
     |> validate_required([:valid_until])
   end
 
@@ -138,6 +160,4 @@ defmodule Pleroma.Web.OAuth.Token do
   end
 
   def is_expired?(_), do: false
-
-  defp expires_in, do: Pleroma.Config.get([:oauth2, :token_expires_in], 600)
 end