Konečné řešení komponenty vyhledávacího formuláře nebo login formuláře?

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

Už našel někdo rozumné řešení pro klasický login form na každé stránce nebo na vyhledávací form na každé stránce?

1. Login form

Požadavky:
1. objevuje se na každé stránce,
2. jeho zpracování by měl řídit nějaký jiný presenter než aktuální, proč? v klasickém designu není prostor pro zobrazovaní chybových stavů, při úspěšném přihlášení je nutné o tom uživatele informovat, věřte nebo ne, ale dost často jsem kdysi řešil, že je to nepřihlásilo přitom byli přihlášení, jen jim prej zmizel přihlašovací login form,
také při neúspěšném přihlášení je nutné nabídnout registraci, vypsat někde hlášky a vykreslit form znovu hned pod hláškou, nabídnout funkci zapomenuté heslo atd. vypsat malinkou hlášku nad tím malinkým loginformem v sidebaru to opravdu nestačí!

2. Search form

Požadavky:
1. objevuje se na každé stránce
2. odesílá se metodou get a zapisuje se do url, opět zpracovává jiný presenter, který má možnost rozšířit parametry vyhledávání, např. o přesnou frázi, volnou shodu atd. atd.

3. a další formy a komponenty

podobně můžeme pokračovat s dalšími komponentami (newsletter subscribe, atd.)

Řešení:

  1. Předpokládám, že by jste na to všichni šli tak, že v basepresenteru vytvoříte továrničkou komponenty na tyto všechny controly LoginControl, NewsLetterControl, QuickSearchControl atd.
  2. Otázka je, jak přesměrovat z komponenty (a formu v komponentě) na jiný presenter a jak nastavit onsubmit?
  3. setmethod get mi vyhazuje vyjímku, krom toho, to co chcete aby bylo v url nastavíte jako persistentní parametry?

ať hledám jak hledám, tak ve foru se už mnohokrát tohle řešilo, ale mám pocit, že nikdy nedošlo k nějakému rozumnému řešení?

co vy na to?

https://forum.nette.org/…jine-strance

$form->onSubmit[] = array('HledaniPresenter', 'hledaniFormSubmitted');

tohle asi neni moc rozumne pouziti, protoze tam nikdy nedojde k presmerovani na ten presenter, ale vola se staticky HledaniPresenter::hledaniFormSubmitted coz neni moc košér

https://forum.nette.org/…m-ako-parent

tady je asi přínosný komentář Joda:

Jednoduché riešenie pomocou BasePresenteru (neni predsa len na registráciu filtrov ,)

Ak myslíš nejaké také prihlasovanie ako je tu , tak to robím cez BasePresenter. Môžeš si spraviť LoginControl ktorý vytvoríš v BasePresenteru a bude na každej stránke v layoute sa vykreslovať. Po odoslaní sa oblúži z metódy formSubmitted v BasePresenteru. Po nesprávnom prihlásení užívateľa môžeš presmerovať na GuestPresenter login ak ti to tam vyhovuje, alebo mu napísať nad formulárom chybu. A nakoniec v GuestPresenteri login buď zmeníš layout, alebo pridáš podmienku aby sa ti ten loginControl nerenderoval tam, ale si ho pridáš do šablony.

tedy co se týče login formu, řešil bych všechny akce jako je přihlášení a odhlášení přímo v komponentě a v důsledku na výsledku bych přesměroval na správné místo

co se týče search form, asi by opět mělo dojít k vygenerování url v komponentě, resp. handle v basepresenteru a jeho přesměrování redirectem na příšlušný presenter již s uvedenou správnou url

co se týče newsletteru je to asi podobné, pokud je něco na každé stránce, asi by se to mělo být schopné zpracovat na každé stránce a pak pouze přesměrovat na správný presenter s parametry předanými v get nebo session

případně pokud opravdu trváte na jiném presenteru co zpracuje formulář, chtělo by to něco jako

$form=new AppForm($this, $name);
$form->setAction($this->presenter->link('Login:', array(Presenter::SIGNAL_KEY => $form->lookupPath('Nette\Application\Presenter') . Presenter::NAME_SEPARATOR . 'submit')));
hjr
Člen | 24
+
0
-

Konečná řešení mám velice rád :)

Ale vážně, zrovna dneska řešíme problém s přihlašovacím formulářem. Klasická potíž je, jak přesměrovat uživatele po přihlášení na tu stránku, na které se přihlásil.

V zásadě jsou dvě možná řešení:

  1. Každá stránka umí přihlášení (tj. signál login v BasePresenteru například)
  2. Na přihlášení je dedikované URL/presenter a používá se nějaký mechanismus přesměrování zpět

Řešení A) se jeví jako snadnější (velmi lehce se dostaneme zpět na stránku, kde uživatel klikl na „přihlásit“), ale v praxi se moc nevidí. Přemýšlel jsem, proč tomu tak je a napadlo mě několik důvodů:

  • problémy se subdoménami:
    • „zapamatovat přihlášení“ v prohlížeči je vázané na doménu
    • přihlašování přes SSL (certifikát vázaný na doménu)
  • phishing: není možné uživateli vtloukat do hlavy, že jediný správný formulář je na této (snadno zapamatovatelné) URL

Tenhle způsob jsem tedy musel zavrhnout a zbývá nám varianta B) a otázka: Jak nejlépe řešit přesměrování zpět na stránku, na které uživatel klikl na „příhlásit“ ?

  • posílat zpětný link v GET parametrech
  • referer

Obojí má svoje výhody a nevýhody, které tady nebudu rozepisovat, rád bych se totiž zeptal na váš názor a zkušenosti, popřípadě se přimluvil za příslušný oddíl v dokumentaci, nějaké best practices apod.

mcmatak
Člen | 487
+
0
-

nejsem si jist jestli vidím ten problém, nejde ti náhodou o tohle?

<?php
$this->getApplication()->restoreRequest($this->backlink);
?>

tedy referer, verze B

Editoval mcmatak (11. 12. 2009 12:59)

hjr
Člen | 24
+
0
-

To si úplně nerozumíme, ale to je asi i moje vina, takže to rozvedu a doplním:

Nejde mi o situaci, kdy by vedl přímo nějaký odkaz na stránku dostupnou jen přihlášeným uživatelům s určitými právy (to řeší store a restoreRequest). Jde mi o situaci, kdy nepřihlášený uživatel má web dostupný „read-only“ a po přihlášení jsou mu dostupné další funkce. Pokud tedy nejsem přihlášený, mám na každé stránce někde odkaz „přihlásit“, který má uskutečnit přihlášení a přesměrovat zpět tam, kde jsem na ten odkaz klikl.

Z důvodů uvedených výše je použitelná pouze varianta B, přihlašování má vlastní presenter a mechanismus přesměrování zpět. Samozřejmě AuthPresenter tedy musí znát stránku, na kterou má přihlášeného uživatele vrátit. Přináší to minimálně tři problémy:

  • na některé presentery nemá smysl/je nežádoucí přesměrovávat zpátky (například registrační formulář, odhlášení uživatele apod.)
  • hlídat podstrčenou cizí URL (technicky to ničemu nevadí, ale je to hloupé)
  • kvůli požadavku na jedinou přihlašovací URL je nutno odkaz na původní stránku nemít v URL

Napadly mě tři varianty řešení:

  1. mít signál login na BasePresenteru, který udělá storeRequest a pošle na login URL
  2. posílat odkaz v GET parametru na login URL
  3. využívat referer

První a druhý problém by se dal vyřešit elegantně tím, že si URL přeložím na PresenterRequest a odfiltruju nežádoucí Presentery. Třetí problém řeší sama třetí varianta, ostatní by si musely informaci o zpětné URL uložit do session.

Druhé dvě možnosti jsou implementačně jasné, mě zajímala hlavně první možnost, protože umožňuje zabít dvě mouchy jednou ranou. Nelze podstrčit URL a snadno zkontroluji, jestli má smysl přesměrovávat na původní stránku, protože musím pracovat s původním PresenterRequestem.

Ta se bohužel dá v Nette udělat jen poměrně prasácky, protože neumožňuje uložení modifikovaného PresenterRequestu (je potřeba v něm zrušit daný signál). Musel bych tedy reimplementovat Application::storeRequest, a uložit klon posledního PresenterRequestu, kterému zruším parametr do (aby nedošlo k opětovnému zavolání signálu login na původním Presenteru). Ovšem funguje to a zatím jsem na nic lepšího nepřišel, takže používám tohle řešení.

Na závěr opět otázka: Jde to udělat jednodušeji a lépe?

mcmatak
Člen | 487
+
+1
-
  1. přihlásit by se mělo být možné ze všech stránek, tedy form nebo komponentu na login bych dal do basepresenteru – metoda A – využiji referer – obvykle je přihlašovací form součástí layoutu – takže se vracíš tam, kde si začal
  2. samozřejmě to vždy nemusí být vhodné, viz. co popisuješ, pak nemáš na výběr než přihlášení umožnit pouze na konkrétní adrese – metoda B – v takovém případě ale neřešíš kam po přihlášení ne? protože to prostě presenter nebo komponenta ví ne? pokud jsem se přihlásil tak přece vím že ho mám hodit na hlavní stránku?

2a. ale ty asi myslíš, jsem na stránce košíku, přihlásit se je nutné na spešl page a tak na ni skočím, přihlásím se a teď se chci vrátit zpět na stránku košíku, prostě na tu kde to začalo? hm to řeším uložením refereru při přístupu na loginpresenter do session

klasicky někomu mailem posílám odkaz někde v adminu, jenomže to ho vykopne na login presenter, tam se přihlásí a já chci aby se dostal zpět na původní stránku, takže si šáhnu do session co že to vlastně chtěl