forked from AkkomaGang/akkoma
[#699] add worker to clean expired oauth tokens
This commit is contained in:
parent
714d8d4ef9
commit
620908a2db
8 changed files with 132 additions and 21 deletions
|
@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- OAuth: added support for refresh tokens
|
||||
- Emoji packs and emoji pack manager
|
||||
- Object pruning (`mix pleroma.database prune_objects`)
|
||||
- OAuth: added job to clean expired access tokens
|
||||
|
||||
### Changed
|
||||
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer
|
||||
|
|
|
@ -481,7 +481,9 @@
|
|||
|
||||
config :pleroma, :oauth2,
|
||||
token_expires_in: 600,
|
||||
issue_new_refresh_token: true
|
||||
issue_new_refresh_token: true,
|
||||
clean_expired_tokens: false,
|
||||
clean_expired_tokens_interval: 86_400_000
|
||||
|
||||
config :pleroma, :database, rum_enabled: false
|
||||
|
||||
|
|
|
@ -550,6 +550,8 @@ Configure OAuth 2 provider capabilities:
|
|||
|
||||
* `token_expires_in` - The lifetime in seconds of the access token.
|
||||
* `issue_new_refresh_token` - Keeps old refresh token or generate new refresh token when to obtain an access token.
|
||||
* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`.
|
||||
* `clean_expired_tokens_interval` - Interval to run the job to clean expired tokens. Defaults to `86_400_000` (24 hours).
|
||||
|
||||
## :emoji
|
||||
* `shortcode_globs`: Location of custom emoji files. `*` can be used as a wildcard. Example `["/emoji/custom/**/*.png"]`
|
||||
|
|
|
@ -110,6 +110,7 @@ def start(_type, _args) do
|
|||
hackney_pool_children() ++
|
||||
[
|
||||
worker(Pleroma.Web.Federator.RetryQueue, []),
|
||||
worker(Pleroma.Web.OAuth.Token.CleanWorker, []),
|
||||
worker(Pleroma.Stats, []),
|
||||
worker(Task, [&Pleroma.Web.Push.init/0], restart: :temporary, id: :web_push_init),
|
||||
worker(Task, [&Pleroma.Web.Federator.init/0], restart: :temporary, id: :federator_init)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
defmodule Pleroma.Web.OAuth.Token do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.Repo
|
||||
|
@ -13,6 +12,7 @@ defmodule Pleroma.Web.OAuth.Token do
|
|||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web.OAuth.Authorization
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
alias Pleroma.Web.OAuth.Token.Query
|
||||
|
||||
@expires_in Pleroma.Config.get([:oauth2, :token_expires_in], 600)
|
||||
@type t :: %__MODULE__{}
|
||||
|
@ -31,17 +31,17 @@ defmodule Pleroma.Web.OAuth.Token do
|
|||
@doc "Gets token for app by access token"
|
||||
@spec get_by_token(App.t(), String.t()) :: {:ok, t()} | {:error, :not_found}
|
||||
def get_by_token(%App{id: app_id} = _app, token) do
|
||||
from(t in __MODULE__, where: t.app_id == ^app_id and t.token == ^token)
|
||||
Query.get_by_app(app_id)
|
||||
|> Query.get_by_token(token)
|
||||
|> Repo.find_resource()
|
||||
end
|
||||
|
||||
@doc "Gets token for app by refresh token"
|
||||
@spec get_by_refresh_token(App.t(), String.t()) :: {:ok, t()} | {:error, :not_found}
|
||||
def get_by_refresh_token(%App{id: app_id} = _app, token) do
|
||||
from(t in __MODULE__,
|
||||
where: t.app_id == ^app_id and t.refresh_token == ^token,
|
||||
preload: [:user]
|
||||
)
|
||||
Query.get_by_app(app_id)
|
||||
|> Query.get_by_refresh_token(token)
|
||||
|> Query.preload([:user])
|
||||
|> Repo.find_resource()
|
||||
end
|
||||
|
||||
|
@ -97,29 +97,25 @@ def create_token(%App{} = app, %User{} = user, attrs \\ %{}) do
|
|||
end
|
||||
|
||||
def delete_user_tokens(%User{id: user_id}) do
|
||||
from(
|
||||
t in Token,
|
||||
where: t.user_id == ^user_id
|
||||
)
|
||||
Query.get_by_user(user_id)
|
||||
|> Repo.delete_all()
|
||||
end
|
||||
|
||||
def delete_user_token(%User{id: user_id}, token_id) do
|
||||
from(
|
||||
t in Token,
|
||||
where: t.user_id == ^user_id,
|
||||
where: t.id == ^token_id
|
||||
)
|
||||
Query.get_by_user(user_id)
|
||||
|> Query.get_by_id(token_id)
|
||||
|> Repo.delete_all()
|
||||
end
|
||||
|
||||
def delete_expired_tokens do
|
||||
Query.get_expired_tokens()
|
||||
|> Repo.delete_all()
|
||||
end
|
||||
|
||||
def get_user_tokens(%User{id: user_id}) do
|
||||
from(
|
||||
t in Token,
|
||||
where: t.user_id == ^user_id
|
||||
)
|
||||
Query.get_by_user(user_id)
|
||||
|> Query.preload([:app])
|
||||
|> Repo.all()
|
||||
|> Repo.preload(:app)
|
||||
end
|
||||
|
||||
def is_expired?(%__MODULE__{valid_until: valid_until}) do
|
||||
|
|
41
lib/pleroma/web/oauth/token/clean_worker.ex
Normal file
41
lib/pleroma/web/oauth/token/clean_worker.ex
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.OAuth.Token.CleanWorker do
|
||||
@moduledoc """
|
||||
The module represents functions to clean an expired oauth tokens.
|
||||
"""
|
||||
|
||||
# 10 seconds
|
||||
@start_interval 10_000
|
||||
@interval Pleroma.Config.get(
|
||||
# 24 hours
|
||||
[:oauth2, :clean_expired_tokens_interval],
|
||||
86_400_000
|
||||
)
|
||||
@queue :background
|
||||
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
def start_link, do: GenServer.start_link(__MODULE__, nil)
|
||||
|
||||
def init(_) do
|
||||
if Pleroma.Config.get([:oauth2, :clean_expired_tokens], false) do
|
||||
Process.send_after(self(), :perform, @start_interval)
|
||||
{:ok, nil}
|
||||
else
|
||||
:ignore
|
||||
end
|
||||
end
|
||||
|
||||
@doc false
|
||||
def handle_info(:perform, state) do
|
||||
Process.send_after(self(), :perform, @interval)
|
||||
PleromaJobQueue.enqueue(@queue, __MODULE__, [:clean])
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
# Job Worker Callbacks
|
||||
def perform(:clean), do: Token.delete_expired_tokens()
|
||||
end
|
55
lib/pleroma/web/oauth/token/query.ex
Normal file
55
lib/pleroma/web/oauth/token/query.ex
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.OAuth.Token.Query do
|
||||
@moduledoc """
|
||||
Contains queries for OAuth Token.
|
||||
"""
|
||||
|
||||
import Ecto.Query, only: [from: 2]
|
||||
|
||||
@type query :: Ecto.Queryable.t() | Token.t()
|
||||
|
||||
alias Pleroma.Web.OAuth.Token
|
||||
|
||||
@spec get_by_refresh_token(query, String.t()) :: query
|
||||
def get_by_refresh_token(query \\ Token, refresh_token) do
|
||||
from(q in query, where: q.refresh_token == ^refresh_token)
|
||||
end
|
||||
|
||||
@spec get_by_token(query, String.t()) :: query
|
||||
def get_by_token(query \\ Token, token) do
|
||||
from(q in query, where: q.token == ^token)
|
||||
end
|
||||
|
||||
@spec get_by_app(query, String.t()) :: query
|
||||
def get_by_app(query \\ Token, app_id) do
|
||||
from(q in query, where: q.app_id == ^app_id)
|
||||
end
|
||||
|
||||
@spec get_by_id(query, String.t()) :: query
|
||||
def get_by_id(query \\ Token, id) do
|
||||
from(q in query, where: q.id == ^id)
|
||||
end
|
||||
|
||||
@spec get_expired_tokens(query, DateTime.t() | nil) :: query
|
||||
def get_expired_tokens(query \\ Token, date \\ nil) do
|
||||
expired_date = date || Timex.now()
|
||||
from(q in query, where: fragment("?", q.valid_until) < ^expired_date)
|
||||
end
|
||||
|
||||
@spec get_by_user(query, String.t()) :: query
|
||||
def get_by_user(query \\ Token, user_id) do
|
||||
from(q in query, where: q.user_id == ^user_id)
|
||||
end
|
||||
|
||||
@spec preload(query, any) :: query
|
||||
def preload(query \\ Token, assoc_preload \\ [])
|
||||
|
||||
def preload(query, assoc_preload) when is_list(assoc_preload) do
|
||||
from(q in query, preload: ^assoc_preload)
|
||||
end
|
||||
|
||||
def preload(query, _assoc_preload), do: query
|
||||
end
|
|
@ -69,4 +69,17 @@ test "deletes all tokens of a user" do
|
|||
|
||||
assert tokens == 2
|
||||
end
|
||||
|
||||
test "deletes expired tokens" do
|
||||
insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3))
|
||||
insert(:oauth_token, valid_until: Timex.shift(Timex.now(), days: -3))
|
||||
t3 = insert(:oauth_token)
|
||||
t4 = insert(:oauth_token, valid_until: Timex.shift(Timex.now(), minutes: 10))
|
||||
{tokens, _} = Token.delete_expired_tokens()
|
||||
assert tokens == 2
|
||||
available_tokens = Pleroma.Repo.all(Token)
|
||||
|
||||
token_ids = available_tokens |> Enum.map(& &1.id)
|
||||
assert token_ids == [t3.id, t4.id]
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue