diff --git a/src/Database/DBA.php b/src/Database/DBA.php index bbf134e8a..228565f94 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -1484,6 +1484,8 @@ class DBA $new_values = array_merge($new_values, array_values($value)); $placeholders = substr(str_repeat("?, ", count($value)), 0, -2); $condition_string .= "`" . $field . "` IN (" . $placeholders . ")"; + } elseif (is_null($value)) { + $condition_string .= "`" . $field . "` IS NULL"; } else { $new_values[$field] = $value; $condition_string .= "`" . $field . "` = ?"; diff --git a/src/Model/TwoFactorRecoveryCode.php b/src/Model/TwoFactorRecoveryCode.php new file mode 100644 index 000000000..82740d3b3 --- /dev/null +++ b/src/Model/TwoFactorRecoveryCode.php @@ -0,0 +1,70 @@ + $uid, 'used' => null]); + } + + public static function existsForUser($uid, $code) + { + return DBA::exists('2fa_recovery_codes', ['uid' => $uid, 'code' => $code, 'used' => null]); + } + + public static function getListForUser($uid) + { + $codesStmt = DBA::select('2fa_recovery_codes', ['code', 'used'], ['uid' => $uid]); + + return DBA::toArray($codesStmt); + } + + public static function markUsedForUser($uid, $code) + { + DBA::update('2fa_recovery_codes', ['used' => DateTimeFormat::utcNow()], ['uid' => $uid, 'code' => $code]); + + return DBA::affectedRows() > 0; + } + + public static function generateForUser($uid) + { + $Random = (new Random())->pattern('[a-z0-9]'); + + $RecoveryGenerator = new Recovery($Random); + + $codes = $RecoveryGenerator + ->setCount(12) + ->setBlocks(2) + ->setChars(6) + ->lowercase(true) + ->toArray(); + + $generated = DateTimeFormat::utcNow(); + foreach ($codes as $code) { + DBA::insert('2fa_recovery_codes', [ + 'uid' => $uid, + 'code' => $code, + 'generated' => $generated + ]); + } + } + + public static function deleteForUser($uid) + { + DBA::delete('2fa_recovery_codes', ['uid' => $uid]); + } + + public static function regenerateForUser($uid) + { + self::deleteForUser($uid); + self::generateForUser($uid); + } +}