From 665f6f09a07fa9d1d813e8343f1687b369e7f3dc Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Tue, 11 Jun 2024 04:50:51 -0400
Subject: [PATCH] Add expired/revoked scopes for doorkeeper models via
 extension modules (#29936)

---
 app/lib/access_grant_extension.rb      | 10 ++++++++++
 app/lib/access_token_extension.rb      |  4 ++++
 app/lib/vacuum/access_tokens_vacuum.rb |  8 ++++----
 app/models/web/push_subscription.rb    |  2 +-
 config/application.rb                  |  1 +
 5 files changed, 20 insertions(+), 5 deletions(-)
 create mode 100644 app/lib/access_grant_extension.rb

diff --git a/app/lib/access_grant_extension.rb b/app/lib/access_grant_extension.rb
new file mode 100644
index 000000000..bf8f5ae25
--- /dev/null
+++ b/app/lib/access_grant_extension.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module AccessGrantExtension
+  extend ActiveSupport::Concern
+
+  included do
+    scope :expired, -> { where.not(expires_in: nil).where('created_at + MAKE_INTERVAL(secs => expires_in) < NOW()') }
+    scope :revoked, -> { where.not(revoked_at: nil).where(revoked_at: ...Time.now.utc) }
+  end
+end
diff --git a/app/lib/access_token_extension.rb b/app/lib/access_token_extension.rb
index 4e9585dd1..6e06f988a 100644
--- a/app/lib/access_token_extension.rb
+++ b/app/lib/access_token_extension.rb
@@ -9,6 +9,10 @@ module AccessTokenExtension
     has_many :web_push_subscriptions, class_name: 'Web::PushSubscription', inverse_of: :access_token
 
     after_commit :push_to_streaming_api
+
+    scope :expired, -> { where.not(expires_in: nil).where('created_at + MAKE_INTERVAL(secs => expires_in) < NOW()') }
+    scope :not_revoked, -> { where(revoked_at: nil) }
+    scope :revoked, -> { where.not(revoked_at: nil).where(revoked_at: ...Time.now.utc) }
   end
 
   def revoke(clock = Time)
diff --git a/app/lib/vacuum/access_tokens_vacuum.rb b/app/lib/vacuum/access_tokens_vacuum.rb
index a224f6d63..281ae22bf 100644
--- a/app/lib/vacuum/access_tokens_vacuum.rb
+++ b/app/lib/vacuum/access_tokens_vacuum.rb
@@ -9,12 +9,12 @@ class Vacuum::AccessTokensVacuum
   private
 
   def vacuum_revoked_access_tokens!
-    Doorkeeper::AccessToken.where.not(expires_in: nil).where('created_at + make_interval(secs => expires_in) < NOW()').in_batches.delete_all
-    Doorkeeper::AccessToken.where.not(revoked_at: nil).where('revoked_at < NOW()').in_batches.delete_all
+    Doorkeeper::AccessToken.expired.in_batches.delete_all
+    Doorkeeper::AccessToken.revoked.in_batches.delete_all
   end
 
   def vacuum_revoked_access_grants!
-    Doorkeeper::AccessGrant.where.not(expires_in: nil).where('created_at + make_interval(secs => expires_in) < NOW()').in_batches.delete_all
-    Doorkeeper::AccessGrant.where.not(revoked_at: nil).where('revoked_at < NOW()').in_batches.delete_all
+    Doorkeeper::AccessGrant.expired.in_batches.delete_all
+    Doorkeeper::AccessGrant.revoked.in_batches.delete_all
   end
 end
diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb
index b482ad3af..ddfd08146 100644
--- a/app/models/web/push_subscription.rb
+++ b/app/models/web/push_subscription.rb
@@ -75,7 +75,7 @@ class Web::PushSubscription < ApplicationRecord
 
   class << self
     def unsubscribe_for(application_id, resource_owner)
-      access_token_ids = Doorkeeper::AccessToken.where(application_id: application_id, resource_owner_id: resource_owner.id, revoked_at: nil).pluck(:id)
+      access_token_ids = Doorkeeper::AccessToken.where(application_id: application_id, resource_owner_id: resource_owner.id).not_revoked.pluck(:id)
       where(access_token_id: access_token_ids).delete_all
     end
   end
diff --git a/config/application.rb b/config/application.rb
index b3a9b99ff..65407da05 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -115,6 +115,7 @@ module Mastodon
       Doorkeeper::AuthorizationsController.layout 'modal'
       Doorkeeper::AuthorizedApplicationsController.layout 'admin'
       Doorkeeper::Application.include ApplicationExtension
+      Doorkeeper::AccessGrant.include AccessGrantExtension
       Doorkeeper::AccessToken.include AccessTokenExtension
       Devise::FailureApp.include AbstractController::Callbacks
       Devise::FailureApp.include Localized