<commit_before><?php

namespace App\Helpers;

use Latte;
use Nette\Utils\Arrays;

use Kdyby\Doctrine\EntityManager;
use App\Model\Entity\Login;
use App\Model\Entity\ForgottenPassword;
use App\Security\AccessToken;
use App\Security\AccessManager;

use DateTime;
use DateInterval;

/**
 * Sending error reports to administrator by email.
 */
class ForgottenPasswordHelper {

  /**
   * Database entity manager
   * @var EntityManager
   */
  private $em;

  /**
   * Emails sending component
   * @var EmailHelper
   */
  private $emailHelper;

  /**
   * Sender address of all mails, something like "<EMAIL>"
   * @var string
   */
  private $sender;

  /**
   * Prefix of mail subject to be used
   * @var string
   */
  private $subjectPrefix;

  /**
   * URL which will be sent to user with token.
   * @var string
   */
  private $redirectUrl;

  /**
   * Expiration period of the change-password token in seconds
   * @var int
   */
  private $tokenExpiration;

  /**
   * @var AccessManager
   */
  private $accessManager;

  /**
   * Constructor
   * @param \App\Helpers\EmailHelper $emailHelper
   */
  public function __construct(EntityManager $em, EmailHelper $emailHelper, AccessManager $accessManager , array $params) {
    $this->em = $em;
    $this->emailHelper = $emailHelper;
    $this->accessManager = $accessManager;
    $this->sender = Arrays::get($params, ["emails", "from"], "<EMAIL>");
    $this->subjectPrefix = Arrays::get($params, ["emails", "subjectPrefix"], "ReCodEx Forgotten Password Request - ");
    $this->redirectUrl = Arrays::get($params, ["redirectUrl"], "https://recodex.cz");
    $this->tokenExpiration = Arrays::get($params, ["tokenExpiration"], 10 * 60); // default value: 10 minutes
  }

  /**
   * Generate access token and send it to the given email.
   * @param Login $login
   */
  public function process(Login $login) {
    // Stalk forgotten password requests a little bit and store them to database
    $entry = new ForgottenPassword($login->user, $login->user->email, $this->redirectUrl);
    $this->em->persist($entry);
    $this->em->flush();

    // prepare all necessary things
    $token = $this->accessManager->issueToken($login->user, [ AccessToken::SCOPE_CHANGE_PASSWORD ], $this->tokenExpiration);
    $subject = $this->createSubject($login);
    $message = $this->createBody($login, $token);

    // Send the mail
    return $this->emailHelper->send(
      $this->sender,
      [ $login->user->email ],
      $subject,
      $message
    );
  }

  private function createSubject(Login $login): string {
    return $this->subjectPrefix . " " . $login->username;
  }

  private function createBody(Login $login, string $token): string {
    // show to user a minute less, so he doesn't waste time ;-)
    $exp = $this->tokenExpiration - 60;
    $expiresAfter = (new DateTime)->add(new DateInterval("PT{$exp}S"));

    // render the HTML to string using Latte engine
    $latte = new Latte\Engine;
    return $latte->renderToString(__DIR__ . "/resetPasswordEmail.latte", [
      "username" => $login->username,
      "link" => "{$this->redirectUrl}#{$token}",
      "expiresAfter" => $expiresAfter->format("H:i")
    ]);
  }
<commit_msg>ForgottenPasswordHelper documentation<commit_after><?php

namespace App\Helpers;

use Latte;
use Nette\Utils\Arrays;
use Kdyby\Doctrine\EntityManager;
use App\Model\Entity\Login;
use App\Model\Entity\ForgottenPassword;
use App\Security\AccessToken;
use App\Security\AccessManager;
use DateTime;
use DateInterval;

/**
 * Provides all necessary things which are needed on forgotten password request.
 */
class ForgottenPasswordHelper {

  /**
   * Database entity manager
   * @var EntityManager
   */
  private $em;

  /**
   * Emails sending component
   * @var EmailHelper
   */
  private $emailHelper;

  /**
   * Sender address of all mails, something like "<EMAIL>"
   * @var string
   */
  private $sender;

  /**
   * Prefix of mail subject to be used
   * @var string
   */
  private $subjectPrefix;

  /**
   * URL which will be sent to user with token.
   * @var string
   */
  private $redirectUrl;

  /**
   * Expiration period of the change-password token in seconds
   * @var int
   */
  private $tokenExpiration;

  /**
   * @var AccessManager
   */
  private $accessManager;

  /**
   * Constructor
   * @param EntityManager $em
   * @param EmailHelper $emailHelper
   * @param AccessManager $accessManager
   * @param array $params Parameters from configuration file
   */
  public function __construct(EntityManager $em, EmailHelper $emailHelper, AccessManager $accessManager , array $params) {
    $this->em = $em;
    $this->emailHelper = $emailHelper;
    $this->accessManager = $accessManager;
    $this->sender = Arrays::get($params, ["emails", "from"], "<EMAIL>");
    $this->subjectPrefix = Arrays::get($params, ["emails", "subjectPrefix"], "ReCodEx Forgotten Password Request - ");
    $this->redirectUrl = Arrays::get($params, ["redirectUrl"], "https://recodex.cz");
    $this->tokenExpiration = Arrays::get($params, ["tokenExpiration"], 10 * 60); // default value: 10 minutes
  }

  /**
   * Generate access token and send it to the given email.
   * @param Login $login
   * @return bool If sending was successful or not
   */
  public function process(Login $login) {
    // Stalk forgotten password requests a little bit and store them to database
    $entry = new ForgottenPassword($login->user, $login->user->email, $this->redirectUrl);
    $this->em->persist($entry);
    $this->em->flush();

    // prepare all necessary things
    $token = $this->accessManager->issueToken($login->user, [ AccessToken::SCOPE_CHANGE_PASSWORD ], $this->tokenExpiration);
    $subject = $this->createSubject($login);
    $message = $this->createBody($login, $token);

    // Send the mail
    return $this->emailHelper->send(
      $this->sender,
      [ $login->user->email ],
      $subject,
      $message
    );
  }

  /**
   * Creates and returns subject of email message.
   * @param Login $login
   * @return string
   */
  private function createSubject(Login $login): string {
    return $this->subjectPrefix . " " . $login->username;
  }

  /**
   * Creates and return body of email message.
   * @param Login $login
   * @param string $token
   * @return string
   */
  private function createBody(Login $login, string $token): string {
    // show to user a minute less, so he doesn't waste time ;-)
    $exp = $this->tokenExpiration - 60;
    $expiresAfter = (new DateTime)->add(new DateInterval("PT{$exp}S"));

    // render the HTML to string using Latte engine
    $latte = new Latte\Engine;
    return $latte->renderToString(__DIR__ . "/resetPasswordEmail.latte", [
      "username" => $login->username,
      "link" => "{$this->redirectUrl}#{$token}",
      "expiresAfter" => $expiresAfter->format("H:i")
    ]);
  }

{'fraction_non_alphanumeric': 0.14365044571094548, 'fraction_numerical': 0.002338155779628818, 'mean_word_length': 3.3289057558507276, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 81, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6613670', 'n_tokens_mistral': 2100, 'n_tokens_neox': 2049, 'n_words': 559}