Konečné řešení komponenty vyhledávacího formuláře nebo login formuláře?
- mcmatak
- Člen | 504
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í:
- 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.
- Otázka je, jak přesměrovat z komponenty (a formu v komponentě) na jiný presenter a jak nastavit onsubmit?
- 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
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í:
- Každá stránka umí přihlášení (tj. signál login v BasePresenteru například)
- 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.
- hjr
- Člen | 24
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í:
- mít signál
login
naBasePresenteru
, který udělá storeRequest a pošle na login URL - posílat odkaz v GET parametru na login URL
- 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
PresenterRequest
em.
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
PresenterRequest
u, 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 | 504
- 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
- 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