From c28528dca3e3a1b654e9f041bd06dfce136f5272 Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Wed, 22 Mar 2023 10:20:59 +0000
Subject: [PATCH] garbage collect expired tfa tokens, fixes #2399

Closes #2399

Merge request studip/studip!1592
---
 lib/cronjobs/garbage_collector.class.php |  6 ++++++
 lib/models/TFASecret.php                 | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/lib/cronjobs/garbage_collector.class.php b/lib/cronjobs/garbage_collector.class.php
index 5e7f911f21f..7adb0cd38f8 100644
--- a/lib/cronjobs/garbage_collector.class.php
+++ b/lib/cronjobs/garbage_collector.class.php
@@ -176,5 +176,11 @@ class GarbageCollectorJob extends CronJob
         if ($removed > 0 && $parameters['verbose']) {
             printf(_('Gelöschte Terminblöcke: %u') . "\n", $removed);
         }
+
+        // Remove expired tfa tokens
+        TFAToken::deleteBySQL(
+            'mkdate < UNIX_TIMESTAMP() - ?',
+            [TFASecret::getGreatestValidityDuration()]
+        );
     }
 }
diff --git a/lib/models/TFASecret.php b/lib/models/TFASecret.php
index 29f42eb3fb2..aa863946c9b 100644
--- a/lib/models/TFASecret.php
+++ b/lib/models/TFASecret.php
@@ -58,6 +58,24 @@ class TFASecret extends SimpleORMap
         $t = self::TYPES[$type];
         return $t['window'] * $t['period'];
     }
+
+    /**
+     * Returns the greatest validity duration for all defined types.
+     *
+     * @return int
+     */
+    public static function getGreatestValidityDuration(): int
+    {
+        $validity_duration = 0;
+        foreach (self::TYPES as $type) {
+            $duration = $type['window'] * $type['period'];
+            if ($duration > $validity_duration) {
+                $validity_duration = $duration;
+            }
+        }
+        return $validity_duration;
+    }
+
     /**
      * Overwrites the SORM setNew() method. This will create the secret string.
      *
-- 
GitLab