Nemohu zprovoznit (re)storeRequest
- Ondřej Mirtes
- Člen | 1536
Ahoj,
chci zprovoznit restorování requestu – např. pro případ, že uživatel
není přihlášený, vleze, kam guest nemá přístup, tak mu to nastaví
flashMessage, že se má přihlásit, zavolá se storeRequest a přesměruje ho
to na přihlašovací formulář. Při úspěšném přihlášení se zavolá
restoreRequest($this->backlink())
. Jenže se mi to
nepřesměruje na stránku, ze které ho to vyhodilo, ale proběhne redirect,
který je pod tím restoreRequest – pro případ, že není co
restorovat.
Ani se mi při storeRequest nic nepřidává URL, jak by asi mělo.
Kusy kódu:
BasePresenter:
protected function startup() {
parent::startup();
$application = $this->getApplication();
if (!in_array($this->getName(), array($application->errorPresenter, 'Login', 'Registration')) &&
!Environment::getUser()->isAllowed($this->getName(), $this->getAction())) {
if (Environment::getUser()->isAuthenticated()) throw new BadRequestException('Permission denied', 403);
else {
//sem se kód dostane, flashMessage se nastaví a přesměrování proběhne
$application->storeRequest();
$this->flashMessage('Přístup zakázán. Možná jste se zapomněli přihlásit.','error');
$this->redirect('Login:');
}
}
}
LoginPresenter:
public function loginFormSubmitted(AppForm $form) {
try {
$values = $form->getValues();
$user = Environment::getUser();
$user->setExpiration($values['permanentLogin'] ? Environment::getConfig('expiration')->userPermanent : Environment::getConfig('expiration')->user,
!$values['permanentLogin']);
$user->authenticate($values['login'], $values['password']);
$this->flashMessage('Byli jste úspěšně přihlášeni!');
$this->getApplication()->restoreRequest($this->backlink());
$this->redirect('Default:');
} catch (AuthenticationException $e) {
if ($e->getCode() == IAuthenticator::IDENTITY_NOT_FOUND)
$form->addError($e->getMessage());
else {
$this->flashMessage($e->getMessage(),'warning');
$this->redirect('this');
}
}
}
Napadá někoho, v čem je chyba?
Revizi Nette mám nejnovější, 460.
Díky.
- Panda
- Člen | 569
S ukládáním requestu se pracuje trochu jinak…
Při jeho ukládání se Ti vrátí jeho unikátní ID – když si člověk otevře několik tabů a pak zjistí, že není přihlášen, tak nechce, aby ho 5 tabů přesměrovalo na stejnou stránku, ale aby ho každý tab přesměroval tam, kam má. Takže ukládání by mělo vypadat nějak takto:
<?php
$key = $application->storeRequest();
$this->flashMessage('...', 'error');
$this->redirect('Login:', $key);
?>
A v LoginPresenter
:
<?php
public function renderDefault($key = NULL) {
// ...
if ($key) {
$this->getComponent('loginForm')->setDefaults(array('key' => $key));
}
}
protected function createComponentLoginForm()
{
// ...
$form->addHidden('key');
// ...
}
public function loginFormSubmitted(AppForm $form) {
// ...
$this->flashMessage('Byli jste úspěšně přihlášeni!');
if ($values['key']) {
$this->getApplication()->restoreRequest($values['key']);
else
$this->redirect('Default:');
// ...
}
?>
Pokud chceš, můžeš ještě přidat následující metodu, která uživatele přesměruje, pokud už je přihlášený (aby se nemusel přihlašovat ve všech tabech, ale jen v jednom a ostatní jen refreshnout):
<?php
public function actionDefault($key)
{
if (Environment::getUser()->isAuthenticated()) {
if ($key) {
$this->getApplication()->restoreRequest($key);
else
$this->redirect('Default:');
}
}
?>
- Ondřej Brejla
- Člen | 746
To by se mělo šoupnout do dokumentace, nebo to tu zapadne…což by byla veliká škoda…
- Panda
- Člen | 569
jasir napsal(a):
Proč
key
přidávat jako hidden form control a nenechat ho jen jako persistentní parametr LoginPresenteru?
Mno ono není ani potřeba ho dávat persistentní, stačí, když je jako
parametr u action a pak ho jde kdekoliv v presenteru vytáhnout pomocí
$this->getParam('key')
. Osobně to do formuláře cpu jen kvůli
vnitřnímu nutkání, které mi říká, že by ten key měl být k dispozici
i v případě, že callback pro onSubmit
vytáhnu někam mimo
presenter. :-)
- jasir
- Člen | 746
Panda napsal(a):
jasir napsal(a):
Proč
key
přidávat jako hidden form control a nenechat ho jen jako persistentní parametr LoginPresenteru?Mno ono není ani potřeba ho dávat persistentní, stačí, když je jako parametr u action a pak ho jde kdekoliv v presenteru vytáhnout pomocí
$this->getParam('key')
. Osobně to do formuláře cpu jen kvůli vnitřnímu nutkání, které mi říká, že by ten key měl být k dispozici i v případě, že callback proonSubmit
vytáhnu někam mimo presenter. :-)
Ok, dík, já si říkal jestli mi něco neuniká. S tou perzistencí máš pravdu. Ono mimochodem nejlepší je podívat se do příkladu Cd-Collection.
Editoval jasir (24. 7. 2009 16:02)
- Ondřej Mirtes
- Člen | 1536
Díky moc všem. Je pravda, že jsem tuto funkčnost neměl kde vyčíst a v akrabatu jsem tomu nějak nerozuměl, resp. mi to nefungovalo :)
- jasir
- Člen | 746
Panda napsal:
Pokud chceš, můžeš ještě přidat následující metodu, která uživatele přesměruje, pokud už je přihlášený (aby se nemusel přihlašovat ve všech tabech, ale jen v jednom a ostatní jen refreshnout):
Takhle by to asi bylo lepší, kdyby náhodou ten restoreRequest neproběhl (co já vím, schnilá session…), aby se to někam redirectovalo
<?php
public function actionDefault($key)
{
if (Environment::getUser()->isAuthenticated()) {
if ($key)
$this->getApplication()->restoreRequest($key);
}
$this->redirect('Default:');
}
}
?>
Editoval jasir (24. 7. 2009 16:29)
- kravčo
- Člen | 721
Podobnú situáciu riešim hodnú chvíľu aj ja. Najprv vlastný
storeRequest()
potom ohýbanie
Application::storeRequest()
… A stále s tým nie som
spokojný…
Situácia je rovnaká ako opisoval LastHunter. Motivácia trochu iná, o tom viac nižšie…
- príde požiadavka na akciu, ktorá vyžaduje autentifikáciu
- presmerovanie na prihlasovací formulár (storeRequest+redirect)
- odoslanie prihlasovacieho formulára (redirect)
- obnovenie pôvodnej požiadavky (restoreRequest)
Použil som perzistentný parameter _bid :). Problém mi robili flash správy – po obnovení požiadavky som chcel oznámiť úspešné prihlásenie, no flashKey sa stratil, ak som to správne pochopil, tak kvôli kanonikalizácii.
Motiváciou mi bola vlastná skúsenosť – po odoslaní asi hodinu písaného formulára (dlhý text) mi to po odoslaní vynadalo, že nie som prihlásený – a dáta v ťahu… Po novom request uložím prihlásim sa a po jeho obnovení dáta pohodlne uložím… Pričom chcem, aby sa mi zobrazili všetky flash správy, ktoré vznikli – teda typicky správa o opätovnom prihlásení (AuthPresenter) a aj správa o úspešnom uložení dát (EditPresenter) – obe akcie sa totiž vykonali v jednom kroku (z hľadiska používateľa).
Momentálne mi to síce funguje, no musím čachrovať s flash správami a to sa mi nepáči… Vyriešil to niekto elegantnejšie?