Ako zistiť username práve registrovaného užívateľa a vložiť ho do uvítacieho mailu!

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
SontoEremo
Člen | 341
+
0
-

Zdravím,
Rád by som sa Vás opýtal či je možnosť ako zistiť username registrovaného užívateľa a uviesť ho do uvítacieho mailu toho registrovaného užívateľa
čiže:
Ahoj username
ďakujeme za tvoju registráciu bla bla bla…

Nejak ma nenapadá ako sa to dá dostať do latte šablóny.

Všetkým za pomoc,ochotu a odpoveď vopred ďakujem.

ODIS
Člen | 33
+
0
-

Ahoj, prostě po zavolání metody, ve které uživatele registruješ (tím pádem jí určitě předáváš data uživatele, ve kterých je i username), zavolej metodu pro poslání registračního mailu a do ní taky předej tyto údaje, které v mailu vypíšeš. Kdyžtak tu hoď kód toho, jak to řešíš, ať ti to můžeme nastínit objektivněji.

SontoEremo
Člen | 341
+
0
-

Tak som pridal do ->setHtmlBody

'Ahoj' . ' ' . $Registerform['username']->value,

čiže:

$mail = new Message;
            $mail->setFrom('page.xxx <email@email.xxx>')
                 ->addTo($Registerform['email']->value)
                 ->setSubject('Aktivácia účtu')
                 ->setHtmlBody('Ahoj' . ' ' . $Registerform['username']->value, $template);
ODIS
Člen | 33
+
0
-

Ale neprovádíš celý proces registrace jen v jedné metodě na onSuccess formuláře, doufám :).

SontoEremo
Člen | 341
+
0
-

Môj RegisterForm.php používam príklad z „miroslav-mrazek/guestbook
“:https://github.com/…e/master/app

<?php
namespace App\Components;
use Nette;
use Nette\Application\UI\Form;
use Nette\Utils\Html;
use Nette\Security as NS;
use Nette\Mail\Message;
use Nette\Mail\SendmailMailer;
use Nette\Mail\SmtpMailer;
use Nette\Utils\Strings;
use Nette\Templating\FileTemplate;
use Nette\Latte\Engine;
use Nette\Templating\Helpers;
use Nette\Security\AuthenticationException;
use App\Model\UserManager;
use App\Model\UserRepository;

class RegisterForm extends SecuredControl {

	/** @persistent */
    public $backlink = '';

    /** @var UserManager */
    protected  $userManager;

    /** @var UserRepository */
    public $userRepository;

    /**
	* @param UserManager $userManager
	* @param UserRepository $userRepository
	*/
    public function __construct(UserManager $userManager, UserRepository $userRepository) {
    	parent::__construct();
    	$this->userManager = $userManager;
    	$this->userRepository = $userRepository;
    }

	public function render() {
		$this->template->setFile(__DIR__ . '/registerForm.latte');
		$this->template->render();
	}
	/**
	* RegisterForm factory.
	* @return Form
	*/
	protected function createComponentRegisterForm() {
		$repository = $this->userRepository;
		$Registerform = new Form;
		$Registerform->getElementPrototype()->novalidate = 'novalidate';
		$Registerform->addText('username', 'Užívateľské meno')
					 ->setAttribute('class', 'myform-input')
					 ->addRule(Form::MIN_LENGTH, 'Užívateľské meno musí obsahovať aspoň %d znaky', 4)
                     ->addRule(Form::MAX_LENGTH, 'Užívateľské meno môže obsahovať max. %d znakov', 16)
                     ->addRule(function($input) use($repository)
                     {
                        return !$repository->usernameexists($input->value);
                     }, 'Toto užívateľské meno je obsadené prosím vyberte si iné!');
		$Registerform->addText('email', 'Emailová adresa')
					 ->setAttribute('class', 'myform-input')
					 ->addRule(Form::EMAIL, 'Zadajte prosím, platnú emailovú adresu!')
                    ->addRule(function($input) use($repository)
                     {
                        return !$repository->usermailexists($input->value);
                     }, 'Táto emailová adresa je už v systéme zaregistrovaná!');
		$Registerform->addPassword('password', 'Heslo')
					 ->setAttribute('class', 'myform-input')
					 ->addRule(Form::MIN_LENGTH, 'Heslo musí obsahovať aspoň %d znakov', 8)
					 ->addRule(Form::MAX_LENGTH, 'Heslo môže obsahovať max. %d znakov', 32);
		$Registerform->addPassword('confirm_password', 'Potvrďte heslo')
					 ->setAttribute('class', 'myform-input')
					 ->addRule(Form::EQUAL, 'Zadané heslá nie sú zhodné!', $Registerform['password']);
		$Registerform->addSubmit('btnReg', 'Zaregistrovať');
        $Registerform->onSuccess[] = $this->success;
		return $Registerform;
	}
	/**
	* @param Form $Registerform
	*/
	public function success($Registerform) {
		$values = $Registerform->getValues();
		if ($values->password === $values->confirm_password){
			$user = $this->userManager;
			$active = Strings::random(32);
			$date_time = date('d.m.Y H:i:s');
			$ip_adress = $_SERVER['REMOTE_ADDR'];
			$user->add($values->username, $values->email, $values->password, $active, $date_time, $ip_adress);

			$template = new FileTemplate(__DIR__ . '/email.latte');
            $template->registerFilter(new Engine);
            $template->registerHelperLoader('Nette\Templating\Helpers::loader');
            $template->user = $user;
            $template->verifyLink = $this->presenter->link('//Account:verify', array(
                'active' => $active,));

            $mail = new Message;
            $mail->setFrom('WaadLab.xxx <email@email.xxx>')
                 ->addTo($Registerform['email']->value)
                 ->setSubject('Aktivácia účtu')
                 ->setHtmlBody('Ahoj' . ' ' . $Registerform['username']->value, $template);

            $mailer = new SmtpMailer(array(
                'host' => 'smtp.gmail.com',
                'port' => 465,
                'username' => 'email@email.xxx',
                'password' => '**********',
                'secure' => 'ssl',
            ));
            $mailer->send($mail);

			$this->presenter->flashMessage(Html::el('div')
             	 			->setHtml(
				'<h2 class="text-success">
					Registrácia prebehla úspešne <i class="fa fa-smile-o"></i>
				</h2>
				<p>
					Na Vami uvedenú emailovú adresu <strong>' . $values->email . '</strong>
					bol zaslaný aktivačný link.
				</p>
				<p>
					Teraz môžete zavrieť túto stránku a pokračovať
					podľa inštrukcií v emailovej správe.
				</p>
				<h5 class="text-danger">
					nezabudnite si prosím skontrolovať aj zložku SPAM
					<small class="text-danger">(Nevyžiadaná pošta)</small>.
				</h5>
				<p><strong>Ďakujeme Team WaadLab.com™</strong></p>'
				));
            $this->presenter->redirect('RegisterSuccess');
		} else {
            $registerForm->addError($this->getMessage());
        }
	}
}
Jan Tvrdík
Nette guru | 2595
+
0
-

Pozor na XSS! V setHtmlBody chybí htmlspecialchars.

ODIS
Člen | 33
+
0
-

Jakou má v tvoji aplikaci úlohu userRepository a jakou userManager? Zvláštní rozdělení :)

Editoval ODIS (23. 3. 2015 21:22)

ODIS
Člen | 33
+
0
-

Jinak teda do šablony pro mail předáváš userManager a né data vkládaného uživatele.

Editoval ODIS (23. 3. 2015 21:26)

Hurass
Člen | 114
+
0
-

OT, ale to html (flash message) v presenteru nemá co dělat, udělej si třeba šablonu, kterou budeš volat, ale rozhodně pryč s tím z presenteru.

SontoEremo
Člen | 341
+
0
-

@JanTvrdík Pozor na XSS! V setHtmlBody chybí htmlspecialchars.
Ako to myslíš akože to tam mám vpísať?
TAKTO?

->setHtmlBody(htmlspecialchars('Ahoj' . ' ' . $Registerform['username']->value), $template);

@ODIS Jakou má v tvoji aplikaci úlohu userRepository a jakou userManager? Zvláštní rozdělení :)
Môj UserRepository.php

<?php
namespace App\Model;
use Nette;
use Nette\Database\Context;
/**
 * Tabulka user
 */
class UserRepository extends Nette\Object
{
    /** @var Nette\Database\Connection */
    private $database;

    public function __construct(Context $database)
    {
        $this->database = $database;
    }

    public function findAll()
    {
        return $this->database->table('users');
    }

    public function findById($id)
    {
        return $this->findAll()->get($id);
    }

    public function insert($values)
    {
        return $this->findAll()->insert($values);
    }

    public function usernameexists($username)
    {
        return $this->findAll()->select('username')->where('username', $username)->fetch();
    }

    public function usermailexists($email)
    {
        return $this->findAll()->select('email')->where('email', $email)->fetch();
    }
}

A môj UserManager.php

<?php
namespace App\Model;
use Nette;
use Nette\Utils\Strings;
use Nette\Security\Passwords;
use Nette\Security\IAuthenticator;
use Nette\Database\Context;
use App\Errors\ActivatedException;
/**
 * Users management.
 */
class UserManager extends Nette\Object implements IAuthenticator {
	const
		TABLE_NAME = 'users',
		COLUMN_ID = 'id',
		COLUMN_NAME = 'username',
		COLUMN_EMAIL = 'email',
		COLUMN_PASSWORD_HASH = 'password',
		COLUMN_ACTIVE = 'active',
		COLUMN_DATE_TIME = 'date_time',
		COLUMN_IP_ADRESS = 'ip_adress';


	/** @var Nette\Database\Context */
	private $database;


	public function __construct(Context $database) {
		$this->database = $database;
	}


	/**
	 * Performs an authentication.
	 * @return Nette\Security\Identity
	 * @throws Nette\Security\AuthenticationException
	 */
	public function authenticate(array $credentials) {
		list($username, $password) = $credentials;

		$row = $this->database->table(self::TABLE_NAME)->where(self::COLUMN_NAME, $username)->fetch();

		if (!$row) {
			throw new Nette\Security\AuthenticationException('The username is incorrect.', self::IDENTITY_NOT_FOUND);

		} elseif (!Passwords::verify($password, $row[self::COLUMN_PASSWORD_HASH])) {
			throw new Nette\Security\AuthenticationException('The password is incorrect.', self::INVALID_CREDENTIAL);

		} elseif (Passwords::needsRehash($row[self::COLUMN_PASSWORD_HASH])) {
			$row->update(array(
				self::COLUMN_PASSWORD_HASH => Passwords::hash($password),
			));
		} if ($row[self::COLUMN_ACTIVE]) {
            throw new ActivatedException('Váš účet ešte nebol aktivovaný');
        }

		$arr = $row->toArray();
		unset($arr[self::COLUMN_PASSWORD_HASH]);
		return new Nette\Security\Identity($row[self::COLUMN_ID], $arr);
	}


	/**
	 * Adds new user.
	 * @param  string
	 * @param  string
	 * @return void
	 */
	public function add($username, $email, $password, $active, $date_time, $ip_adress){
		try {
			$this->database->table(self::TABLE_NAME)->insert(array(
				self::COLUMN_NAME => $username,
				self::COLUMN_EMAIL => $email,
				self::COLUMN_PASSWORD_HASH => Passwords::hash($password),
				self::COLUMN_ACTIVE => $active,
				self::COLUMN_DATE_TIME => $date_time,
				self::COLUMN_IP_ADRESS => $ip_adress,
			));
		} catch (Nette\Database\UniqueConstraintViolationException $e) {
			throw new DuplicateNameException;
		}
	}

	public function actionVerify($active) {
	    $user = $this->database->table(self::TABLE_NAME)->where(self::COLUMN_ACTIVE, $active)->fetch();
	    if($user) {
	        $user->update(array(self::COLUMN_ACTIVE => NULL));
	        return TRUE;
	    }
	    	return FALSE;
	}
}

class DuplicateNameException extends \Exception {

}

@ODIS Jinak teda do šablony pro mail předáváš userManager a né data vkládaného uživatele.
Tak teda to mám všetko spojiť už len do UserManager.php?

@Hurass OT, ale to html (flash message) v presenteru nemá co dělat, udělej si třeba šablonu, kterou budeš volat, ale rozhodně pryč s tím z presenteru.

Akože nemá co dělat prepáč nechápem tomu mohol by si mi to názorne ukázať alebo dať nejaký odkaz ako to myslíš? Díky

Hurass
Člen | 114
+
0
-

Myslel jsem to tak, že flash message předáš šablonu, která bude obsahovat to html. Úloha prezenteru není cokoliv vypisovat, to je úloha šablon.

ODIS
Člen | 33
+
0
-

Tam kde je kód třeba rozdělit, ho nerozděluješ a tam kde není, ho rozdělíš.
Tady je pár poznámek:

  • myslím, že není vůbec třeba rozdělovat userManager a userRepository, naopak bych tyto třídy sloučil do jedné – fungující jako model (prostuduj trochu architekturu MVC: https://cs.wikipedia.org/…w-controller)
  • osobně si formuláře vyčleňuju jako samostatné komponenty, které si pak injectnu do presenteru (viz https://doc.nette.org/…s/form-reuse)
  • také práci s e-maily apod. je dobré si vyčlenit zvlášť (opět nejlépe do samostatných komponent)

Důvod těchto členění je ten, že si logické části aplikace oddělíš od sebe a pak je můžeš snadněji spravovat a mít nad nimi větší kontrolu. Potom je jako skládačku spojuješ dohromady. Tímto přišpíváš ke znovupoužitelnosti kódu a zabraňuješ zbytečným duplicitám.

Abych ale odpověděl na tvoji původní otázku: „Nejak ma nenapadá ako sa to dá dostať do latte šablóny.“.

V tomhle kusu kódu:

<?php
	// Kde naplňuješ data pro šablonu registračního e-mailu
	$template->user = $user;
?>

máš v proměnné $user uloženou instanci userManagera (z něho v tvém případě nic kloudného nevytáhneš). Takže tam místo toho předej třeba $values (ve kterém máš data uživatele).

Editoval ODIS (24. 3. 2015 20:13)

akadlec
Člen | 1326
+
0
-

jen bych doplnil že maily bych dělal spíše jako službu než jako komponentu

SontoEremo
Člen | 341
+
0
-

akadlec napsal(a):

jen bych doplnil že maily bych dělal spíše jako službu než jako komponentu

Ako myslíš, že službu?

akadlec
Člen | 1326
+
0
-

Tak jak služba funguje aby sis ji pak mohl předávat v konstruktorech a pak jen posílat maily třeba takto:

$this->mailservice->sendOnUserCreate($userDetails);

no a služba zajistí poskládání mailu – předmět, odesílatel, příjemce, text atd.