<commit_before><?php

namespace App\Controller;

use App\Controller\Component\StringComponent;
use App\Lib\PdfWriter\TermsOfUsePdfWriter;
use App\Mailer\AppMailer;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Datasource\Exception\RecordNotFoundException;
use Cake\Core\Configure;
use Cake\Http\Cookie\Cookie;
use Cake\I18n\Date;
use Cake\Log\Log;
use Cake\Utility\Security;
use DateTime;
use Cake\Http\Exception\NotFoundException;

/**
 * FoodCoopShop - The open source software for your foodcoop
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @since         FoodCoopShop 1.0.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 * @author        <NAME> <<EMAIL>>
 * @copyright     Copyright (c) <NAME>, https://www.rothauer-it.com
 * @link          https://www.foodcoopshop.com
 */
class CustomersController extends FrontendController
{

    public function profileImage()
    {
        if (!$this->AppAuth->user() || $this->AppAuth->isManufacturer() || empty($this->request->getParam('imageSrc'))) {
            throw new NotFoundException('image not found');
        }

        // customer exists check (if customer was deleted and somehow files were not deleted)
        $customerId = explode('-', $this->request->getParam('imageSrc'));
        $customerId = $customerId[0];
        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->find('all', [
            'conditions' => [
                'Customers.id_customer' => $customerId
            ],
        ])->first();
        if (empty($customer)) {
            throw new NotFoundException('image not found');
        }

        $this->RequestHandler->renderAs($this, 'jpg');
        $imagePath = Configure::read('app.customerImagesDir') . DS . $this->request->getParam('imageSrc') . '.jpg';
        if (!file_exists($imagePath)) {
            throw new NotFoundException('image not found');
        }
        $this->set('imagePath', $imagePath);
    }

    private function generateTermsOfUsePdf()
    {
        $pdfWriter = new TermsOfUsePdfWriter();
        return $pdfWriter->writeAttachment();
    }

    public function acceptUpdatedTermsOfUse()
    {

        if (!$this->getRequest()->is('post')) {
            $this->redirect('/');
        }

        $this->set('title_for_layout', __('Accept_terms_of_use'));

        $this->Customer = $this->getTableLocator()->get('Customers');
        $patchedEntity = $this->Customer->patchEntity(
            $this->Customer->get($this->AppAuth->getUserId()),
            [
                'Customers' => [
                    'terms_of_use_accepted_date_checkbox' => $this->getRequest()->getData('Customers.terms_of_use_accepted_date_checkbox'),
                    'terms_of_use_accepted_date' => Date::now()
                ]
            ],
            ['validate' => 'termsOfUse']
        );

        $errors = $patchedEntity->getErrors();
        if (isset($errors['terms_of_use_accepted_date'])) {
            $this->AppFlash->setFlashError($errors['terms_of_use_accepted_date']['equals']);
        }

        if (empty($errors)) {
            $this->Customer->save($patchedEntity);
            $this->Flash->success(__('Accepting_the_terms_of_use_have_been_saved.'));
            $this->renewAuthSession();
            $this->redirect($this->referer());
        }
    }

    public function activateEmailAddress()
    {
        $emailActivationCode = h($this->getRequest()->getParam('pass')[0]);

        if (!isset($emailActivationCode)) {
            throw new RecordNotFoundException('activation code not passed');
        }

        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->find('all', [
            'conditions' => [
                'Customers.activate_email_code' => $emailActivationCode,
            ],
            'contain' => [
                'AddressCustomers',
            ]
        ])->first();

        if (empty($customer)) {
            $this->Flash->success(__('Your_email_address_was_already_activated_or_the_activation_code_was_not_valid.'));
        } else {
            $customer->activate_email_code = null;
            $customer->active = true;
            $this->Customer->save($customer);
            $this->AppAuth->setUser($customer);

            $newPassword = $this->Customer->setNewPassword($customer->id_customer);

            $email = new AppMailer();
            $email->viewBuilder()->setTemplate('email_address_activated');
            $email->setTo($customer->email)
            ->setSubject(__('Your_email_address_has_been_activated_successfully.'))
            ->setViewVars([
                'appAuth' => $this->AppAuth,
                'data' => $customer,
                'newPassword' => $<PASSWORD>,
            ]);

            if (Configure::read('app.termsOfUseEnabled')) {
                $email->addAttachments([__d('admin', 'Filename_Terms-of-use').'.pdf' => ['data' => $this->generateTermsOfUsePdf($customer), 'mimetype' => 'application/pdf']]);
            }
            $email->send();

            $this->Flash->success(__('Your_email_address_has_been_activated_successfully and you are already logged in.'));
        }

        $this->redirect('/');

    }

    public function newPasswordRequest()
    {
        $this->set([
            'title_for_layout' => __('Request_new_password')
        ]);

        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->newEntity([]);

        if (!empty($this->getRequest()->getData())) {

            $this->loadComponent('Sanitize');
            $this->setRequest($this->getRequest()->withParsedBody($this->Sanitize->trimRecursive($this->getRequest()->getData())));
            $this->setRequest($this->getRequest()->withParsedBody($this->Sanitize->stripTagsAndPurifyRecursive($this->getRequest()->getData())));

            $customer = $this->Customer->patchEntity(
                $customer,
                $this->getRequest()->getData(),
                [
                    'validate' => 'newPasswordRequest'
                ]
            );

            if ($customer->hasErrors()) {
                $this->Flash->error(__('Errors_while_saving!'));
            } else {

                $originalPrimaryKey = $this->Customer->getPrimaryKey();
                $this->Customer->setPrimaryKey('email');
                $oldEntity = $this->Customer->get($this->getRequest()->getData('Customers.email'));
                $activateNewPasswordCode = $oldEntity->activate_new_password_code;
                $data2save = [];

                if ($activateNewPasswordCode == '') {
                    $activateNewPasswordCode = StringComponent::createRandomString(12);
                    $data2save['activate_new_password_code'] = $activateNewPasswordCode;
                }

                // always generate new password as it's saved as hash and cannot be sent in clear text
                $tmpNewPassword = StringComponent::createRandomString(12);
                $ph = new DefaultPasswordHasher();
                $data2save['tmp_new_passwd'] = $ph->hash($tmpNewPassword);

                $this->Customer->setPrimaryKey($originalPrimaryKey);
                $patchedEntity = $this->Customer->patchEntity(
                    $oldEntity,
                    $data2save
                );
                $this->Customer->save($patchedEntity);

                // send email
                $email = new AppMailer();
                $email->viewBuilder()->setTemplate('new_password_request_successful');
                $email->setSubject(__('New_password_for_{0}', [Configure::read('appDb.FCS_APP_NAME')]))
                    ->setTo($this->getRequest()->getData('Customers.email'))
                    ->setViewVars([
                        'activateNewPasswordCode' => $activateNewPasswordCode,
                        'tmpNewPassword' => $<PASSWORD>,
                        'customer' => $oldEntity
                    ]);

                if ($email->send()) {
                    $this->Flash->success(__('We_sent_your_new_password_to_you_it_needs_to_be_activated.'));
                }

                $this->redirect('/');
            }
        }

        $this->set('customer', $customer);
    }

    public function activateNewPassword()
    {
        $activateNewPasswordCode = h($this->getRequest()->getParam('pass')[0]);

        if (!isset($activateNewPasswordCode)) {
            throw new RecordNotFoundException('activate new password code not passed');
        }

        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->find('all', [
            'conditions' => [
                'Customers.activate_new_password_code' => $activateNewPasswordCode
            ],
        ])->first();

        if (empty($customer)) {
            $this->Flash->success(__('Your_new_password_was_already_activated_or_the_activation_code_was_not_valid.'));
        } else {

            $patchedEntity = $this->Customer->patchEntity(
                $customer,
                [
                    'passwd' => $<PASSWORD>,
                    'tmp_new_passwd' => <PASSWORD>,
                    'activate_new_password_code' => null
                ]
            );
            $this->Customer->save($patchedEntity);
            $this->AppAuth->setUser($patchedEntity);
            $this->Flash->success(__('Your_new_password_was_successfully_activated.'));
        }

        $this->redirect('/');
    }

    public function login()
    {
        $this->Customer = $this->getTableLocator()->get('Customers');
        $title = __('Sign_in');
        $enableRegistrationForm = true;
        $enableBarCodeLogin = false;

        if (Configure::read('appDb.FCS_SELF_SERVICE_MODE_FOR_STOCK_PRODUCTS_ENABLED')
            && ($this->AppAuth->isSelfServiceModeByUrl() || $this->AppAuth->isSelfServiceModeByReferer())<commit_msg>skip auto login - password should be typed by user to update password managers<commit_after><?php

namespace App\Controller;

use App\Controller\Component\StringComponent;
use App\Lib\PdfWriter\TermsOfUsePdfWriter;
use App\Mailer\AppMailer;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Datasource\Exception\RecordNotFoundException;
use Cake\Core\Configure;
use Cake\Http\Cookie\Cookie;
use Cake\I18n\Date;
use Cake\Log\Log;
use Cake\Utility\Security;
use DateTime;
use Cake\Http\Exception\NotFoundException;

/**
 * FoodCoopShop - The open source software for your foodcoop
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @since         FoodCoopShop 1.0.0
 * @license       https://opensource.org/licenses/mit-license.php MIT License
 * @author        <NAME> <<EMAIL>>
 * @copyright     Copyright (c) <NAME>, https://www.rothauer-it.com
 * @link          https://www.foodcoopshop.com
 */
class CustomersController extends FrontendController
{

    public function profileImage()
    {
        if (!$this->AppAuth->user() || $this->AppAuth->isManufacturer() || empty($this->request->getParam('imageSrc'))) {
            throw new NotFoundException('image not found');
        }

        // customer exists check (if customer was deleted and somehow files were not deleted)
        $customerId = explode('-', $this->request->getParam('imageSrc'));
        $customerId = $customerId[0];
        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->find('all', [
            'conditions' => [
                'Customers.id_customer' => $customerId
            ],
        ])->first();
        if (empty($customer)) {
            throw new NotFoundException('image not found');
        }

        $this->RequestHandler->renderAs($this, 'jpg');
        $imagePath = Configure::read('app.customerImagesDir') . DS . $this->request->getParam('imageSrc') . '.jpg';
        if (!file_exists($imagePath)) {
            throw new NotFoundException('image not found');
        }
        $this->set('imagePath', $imagePath);
    }

    private function generateTermsOfUsePdf()
    {
        $pdfWriter = new TermsOfUsePdfWriter();
        return $pdfWriter->writeAttachment();
    }

    public function acceptUpdatedTermsOfUse()
    {

        if (!$this->getRequest()->is('post')) {
            $this->redirect('/');
        }

        $this->set('title_for_layout', __('Accept_terms_of_use'));

        $this->Customer = $this->getTableLocator()->get('Customers');
        $patchedEntity = $this->Customer->patchEntity(
            $this->Customer->get($this->AppAuth->getUserId()),
            [
                'Customers' => [
                    'terms_of_use_accepted_date_checkbox' => $this->getRequest()->getData('Customers.terms_of_use_accepted_date_checkbox'),
                    'terms_of_use_accepted_date' => Date::now()
                ]
            ],
            ['validate' => 'termsOfUse']
        );

        $errors = $patchedEntity->getErrors();
        if (isset($errors['terms_of_use_accepted_date'])) {
            $this->AppFlash->setFlashError($errors['terms_of_use_accepted_date']['equals']);
        }

        if (empty($errors)) {
            $this->Customer->save($patchedEntity);
            $this->Flash->success(__('Accepting_the_terms_of_use_have_been_saved.'));
            $this->renewAuthSession();
            $this->redirect($this->referer());
        }
    }

    public function activateEmailAddress()
    {
        $emailActivationCode = h($this->getRequest()->getParam('pass')[0]);

        if (!isset($emailActivationCode)) {
            throw new RecordNotFoundException('activation code not passed');
        }

        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->find('all', [
            'conditions' => [
                'Customers.activate_email_code' => $emailActivationCode,
            ],
            'contain' => [
                'AddressCustomers',
            ]
        ])->first();

        if (empty($customer)) {
            $this->Flash->success(__('Your_email_address_was_already_activated_or_the_activation_code_was_not_valid.'));
        } else {
            $customer->activate_email_code = null;
            $customer->active = true;
            $this->Customer->save($customer);

            $newPassword = $this->Customer->setNewPassword($customer->id_customer);

            $email = new AppMailer();
            $email->viewBuilder()->setTemplate('email_address_activated');
            $email->setTo($customer->email)
            ->setSubject(__('Your_email_address_has_been_activated_successfully.'))
            ->setViewVars([
                'appAuth' => $this->AppAuth,
                'data' => $customer,
                'newPassword' => $<PASSWORD>,
            ]);

            if (Configure::read('app.termsOfUseEnabled')) {
                $email->addAttachments([__d('admin', 'Filename_Terms-of-use').'.pdf' => ['data' => $this->generateTermsOfUsePdf($customer), 'mimetype' => 'application/pdf']]);
            }
            $email->send();

            $this->Flash->success(__('Your_email_address_has_been_activated_successfully and you are already logged in.'));
        }

        $this->redirect('/');

    }

    public function newPasswordRequest()
    {
        $this->set([
            'title_for_layout' => __('Request_new_password')
        ]);

        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->newEntity([]);

        if (!empty($this->getRequest()->getData())) {

            $this->loadComponent('Sanitize');
            $this->setRequest($this->getRequest()->withParsedBody($this->Sanitize->trimRecursive($this->getRequest()->getData())));
            $this->setRequest($this->getRequest()->withParsedBody($this->Sanitize->stripTagsAndPurifyRecursive($this->getRequest()->getData())));

            $customer = $this->Customer->patchEntity(
                $customer,
                $this->getRequest()->getData(),
                [
                    'validate' => 'newPasswordRequest'
                ]
            );

            if ($customer->hasErrors()) {
                $this->Flash->error(__('Errors_while_saving!'));
            } else {

                $originalPrimaryKey = $this->Customer->getPrimaryKey();
                $this->Customer->setPrimaryKey('email');
                $oldEntity = $this->Customer->get($this->getRequest()->getData('Customers.email'));
                $activateNewPasswordCode = $oldEntity->activate_new_password_code;
                $data2save = [];

                if ($activateNewPasswordCode == '') {
                    $activateNewPasswordCode = StringComponent::createRandomString(12);
                    $data2save['activate_new_password_code'] = $activateNewPasswordCode;
                }

                // always generate new password as it's saved as hash and cannot be sent in clear text
                $tmpNewPassword = StringComponent::createRandomString(12);
                $ph = new DefaultPasswordHasher();
                $data2save['tmp_new_passwd'] = $ph->hash($tmpNewPassword);

                $this->Customer->setPrimaryKey($originalPrimaryKey);
                $patchedEntity = $this->Customer->patchEntity(
                    $oldEntity,
                    $data2save
                );
                $this->Customer->save($patchedEntity);

                // send email
                $email = new AppMailer();
                $email->viewBuilder()->setTemplate('new_password_request_successful');
                $email->setSubject(__('New_password_for_{0}', [Configure::read('appDb.FCS_APP_NAME')]))
                    ->setTo($this->getRequest()->getData('Customers.email'))
                    ->setViewVars([
                        'activateNewPasswordCode' => $activateNewPasswordCode,
                        'tmpNewPassword' => $tmpNewPassword,
                        'customer' => $oldEntity
                    ]);

                if ($email->send()) {
                    $this->Flash->success(__('We_sent_your_new_password_to_you_it_needs_to_be_activated.'));
                }

                $this->redirect('/');
            }
        }

        $this->set('customer', $customer);
    }

    public function activateNewPassword()
    {
        $activateNewPasswordCode = h($this->getRequest()->getParam('pass')[0]);

        if (!isset($activateNewPasswordCode)) {
            throw new RecordNotFoundException('activate new password code not passed');
        }

        $this->Customer = $this->getTableLocator()->get('Customers');
        $customer = $this->Customer->find('all', [
            'conditions' => [
                'Customers.activate_new_password_code' => $activateNewPasswordCode
            ],
        ])->first();

        if (empty($customer)) {
            $this->Flash->success(__('Your_new_password_was_already_activated_or_the_activation_code_was_not_valid.'));
        } else {

            $patchedEntity = $this->Customer->patchEntity(
                $customer,
                [
                    'passwd' => $<PASSWORD>,
                    'tmp_new_passwd' => null,
                    'activate_new_password_code' => null
                ]
            );
            $this->Customer->save($patchedEntity);
            $this->Flash->success(__('Your_new_password_was_successfully_activated.'));
        }

        $this->redirect('/');
    }

    public function login()
    {
        $this->Customer = $this->getTableLocator()->get('Customers');
        $title = __('Sign_in');
        $enableRegistrationForm = true;
        $enableBarCodeLogin = false;

        if (Configure::read('appDb.FCS_SELF_SERVICE_MODE_FOR_STOCK_PRODUCTS_ENABLED')
            && ($this->AppAuth->isSelfServiceModeByUrl() || $this->AppAuth->isSelfServiceModeByReferer())
{'fraction_non_alphanumeric': 0.14794805709754164, 'fraction_numerical': 0.0016851704996034894, 'mean_word_length': 2.254879819325698, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 385, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, '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': '6873298', 'n_tokens_mistral': 5602, 'n_tokens_neox': 5346, 'n_words': 791}