%PDF- %PDF-
Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Cron/ |
Current File : //www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Cron/CheckPasswordsJob.php |
<?php /* * @copyright 2023 Passwords App * * @author Marius David Wieschollek * @license AGPL-3.0 * * This file is part of the Passwords App * created by Marius David Wieschollek. */ namespace OCA\Passwords\Cron; use Exception; use OCA\Passwords\Db\PasswordRevision; use OCA\Passwords\Db\PasswordRevisionMapper; use OCA\Passwords\Exception\Database\DecryptedDataException; use OCA\Passwords\Helper\Settings\UserSettingsHelper; use OCA\Passwords\Services\ConfigurationService; use OCA\Passwords\Services\EnvironmentService; use OCA\Passwords\Services\LoggingService; use OCA\Passwords\Services\MailService; use OCA\Passwords\Services\NotificationService; use OCA\Passwords\Services\PasswordSecurityCheckService; use OCP\AppFramework\Utility\ITimeFactory; use Throwable; /** * Class CheckPasswordsJob * * @package OCA\Passwords\Cron */ class CheckPasswordsJob extends AbstractTimedJob { /** * @var array */ protected array $hashLengths = []; /** * @var array */ protected array $badPasswords = []; /** * CheckPasswordsJob constructor. * * @param ITimeFactory $time * @param LoggingService $logger * @param MailService $mailService * @param ConfigurationService $config * @param EnvironmentService $environment * @param UserSettingsHelper $userSettingsHelper * @param PasswordRevisionMapper $revisionMapper * @param NotificationService $notificationService * @param PasswordSecurityCheckService $securityCheckService */ public function __construct( ITimeFactory $time, LoggingService $logger, protected MailService $mailService, ConfigurationService $config, EnvironmentService $environment, protected UserSettingsHelper $userSettingsHelper, protected PasswordRevisionMapper $revisionMapper, protected NotificationService $notificationService, protected PasswordSecurityCheckService $securityCheckService ) { parent::__construct($time, $logger, $config, $environment); $this->setInterval(24 * 60 * 60); $this->setTimeSensitivity(self::TIME_INSENSITIVE); } /** * @param $argument * * @throws Throwable */ protected function runJob($argument): void { $this->securityCheckService->updateDb(); $this->checkAllPasswordRevisions(); } /** * @throws Exception */ protected function checkAllPasswordRevisions(): void { /** @var PasswordRevision[] $revisions */ $revisions = $this->revisionMapper->findAll(); $badRevisionCounter = 0; foreach($revisions as $revision) { $this->checkHashLength($revision); if($revision->getStatus() === PasswordSecurityCheckService::LEVEL_BAD || $revision->getStatus() === PasswordSecurityCheckService::LEVEL_UNKNOWN) continue; $oldStatusCode = $revision->getStatusCode(); [$statusLevel, $statusCode] = $this->securityCheckService->getRevisionSecurityLevel($revision); if($oldStatusCode !== $statusCode) { $revision->setStatus($statusLevel); $revision->setStatusCode($statusCode); $revision->setUpdated(time()); $this->revisionMapper->update($revision); if($statusLevel === PasswordSecurityCheckService::LEVEL_BAD) { $this->sendBadPasswordNotification($revision); $badRevisionCounter++; } } } $this->notifyUsers(); $this->logger->debugOrInfo(['Checked %s passwords. %s new bad revisions found', count($revisions), $badRevisionCounter], $badRevisionCounter); } /** * */ protected function notifyUsers(): void { foreach($this->badPasswords as $user => $count) { $this->notificationService->sendBadPasswordNotification($user, $count); $this->mailService->sendBadPasswordMail($user, $count); } } /** * @param PasswordRevision $revision */ protected function sendBadPasswordNotification(PasswordRevision $revision): void { try { $current = $this->revisionMapper->findCurrentRevisionByModel($revision->getModel()); if($current->getUuid() === $revision->getUuid()) { $user = $revision->getUserId(); if(!isset($this->badPasswords[ $user ])) { $this->badPasswords[ $user ] = 1; } else { $this->badPasswords[ $user ]++; } } } catch(Throwable $e) { $this->logger->logException($e); } } /** * @param PasswordRevision $revision * * @throws DecryptedDataException * @throws \OCP\DB\Exception */ protected function checkHashLength(PasswordRevision $revision): void { $hashLength = $this->getUserHashLength($revision->getUserId()); if(strlen($revision->getHash()) > $hashLength) { if($hashLength !== 0) { $revision->setHash(substr($revision->getHash(), 0, $hashLength)); } else { $revision->setHash(''); } $this->revisionMapper->update($revision); } } /** * @param $userId * * @return int */ protected function getUserHashLength($userId): int { if(!isset($this->hashLengths[ $userId ])) { try { $this->hashLengths[ $userId ] = $this->userSettingsHelper->get('password.security.hash', $userId); } catch(Throwable $e) { $this->logger->logException($e); $this->hashLengths[ $userId ] = 40; } } return $this->hashLengths[ $userId ]; } }