QuickStart – Odkaz na přihlášení (SignPresenter)

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

Ahojky, jedu podle návodu:

Odkaz na přihlášení
Jak se vlastně dostaneme na přihlašovací stránku? Není zde žádný odkaz, který by na ni vedl. Tak si ho tedy přidáme do šablony app/presenters/templates/@layout.latte. Pokuste se najít vhodné místo, může to být téměř kdekoliv.

<ul class="navig">
    <li><a n:href="Homepage:">Články</a></li>
    {if $user->loggedIn}
        <li><a n:href="Sign:out">Odhlásit</a></li>
    {else}
        <li><a n:href="Sign:in">Přihlásit</a></li>
    {/if}
</ul>

Pokud není uživatel přihlášen, zobrazí se odkaz „Přihlásit“. V opačném případě se zobrazí odkaz „Odhlásit“.
Tuto akci také doplníme do SignPresenter.

Kam to mám vložit do SignPresenter?

Hlásí mi to chybu: syntax error, unexpected ‚<‘, expecting function (T_FUNCTION)
File: …\nette-blog\app\presenters\SignPresenter.php:11

<?php
 2:
 3:    namespace App\Presenters;
 4:
 5:    use Nette;
 6:    use Nette\Application\UI\Form;
 7:
 8:
 9:    class SignPresenter extends Nette\Application\UI\Presenter
10:    {
11:        <ul class="navig">
12:        <li><a n:href="Homepage:">Články</a></li>
13:        {if $user->loggedIn}
14:            <li><a n:href="Sign:out">Odhlásit</a></li>
15:        {else}
?>

Děkuji za radu.

Editoval kotrvecko (9. 10. 2016 12:59)

kotrvecko
Člen | 20
+
0
-

SignPresenter je soubor php, tak mě zaráží, proč mám do něj dávat html. Nemá to být spíše v nějaké další šabloně nebo to stačí označit jako html?

ViPEr*CZ*
Člen | 818
+
0
-

No myšleno je tuto akci Sign:out
Tedy do Presenteru je nutné přidat třeba

public function actionOut() {
    $this->getUser()->logout();
	$this->redirect("Homepage:default");
}

Pak ten link bude v šabloně teprve aktivní/reálný. Jinak se tam místo url bude generovat nějakej error… jako, že neexistuje právě ta daná akce.

Editoval ViPEr*CZ* (9. 10. 2016 13:08)

Jan Mikeš
Člen | 771
+
0
-

Ten kód dej do latte šablony, máš to tam napsáno ;) app/presenters/templates/@layout.latte
Tím může to být téměř kdekoliv je myšleno kdekoliv v té šabloně

@ViPEr*CZ* pokud by signpresenter existoval, tak by se linky normálně vygenerovaly bez erroru

Editoval Lexi (9. 10. 2016 13:09)

kotrvecko
Člen | 20
+
0
-

Aha, takže když to dám pryč a Sign:out už tam mám, tak mám problém s authenticatorem.

Chyba:
Service ‚security.user‘: Multiple services of type Nette\Security\IAuthenticator found: security.authenticator, 28_App_Model_UserManager. If you want to overwrite service security.authenticator, give it proper name.
…\eds-www\nette-blog\app\bootstrap.php:20 source Nette\Configurator->createContainer()

<?php
10:	   $configurator->setTimeZone('Europe/Prague');
11:    $configurator->setTempDirectory(__DIR__ . '/../temp');
12:
13:    $configurator->createRobotLoader()
14:        ->addDirectory(__DIR__)
15:        ->register();
16:
17:    $configurator->addConfig(__DIR__ . '/config/config.neon');
18:    $configurator->addConfig(__DIR__ . '/config/config.local.neon');
19:
20:    $container = $configurator->createContainer();
21:
22:    return $container;
?>
kotrvecko
Člen | 20
+
0
-

Lexi napsal(a):

Ten kód dej do latte šablony, máš to tam napsáno ;) app/presenters/templates/@layout.latte
Tím může to být téměř kdekoliv je myšleno kdekoliv v té šabloně

@ViPEr*CZ* pokud by signpresenter existoval, tak by se linky normálně vygenerovaly bez erroru

V šabloně @layout.latte to mám, ale pod tím je ještě napsáno „Tuto akce také doplníme do SignPresenter.“ Což mě zmátlo.

Jan Mikeš
Člen | 771
+
0
-

Tou akcí je právě myšlen kód co poslal @ViPEr*CZ* , ten je potředa doplnit do SignPresenteru

kotrvecko
Člen | 20
+
0
-

Lexi napsal(a):

Tou akcí je právě myšlen kód co poslal @ViPEr*CZ* , ten je potředa doplnit do SignPresenteru

Ten už tam mám. Problém už mám jen s authenticatorem a containerem viz výše.

Jan Mikeš
Člen | 771
+
0
-

Ukaž tvůj config.neon a config.local.neon

kotrvecko
Člen | 20
+
0
-

„Nette automaticky vytvoří službu s názvem authenticator v DI kontejneru.“
Mám vytvořit nový $container s názvem DI? :-D

kotrvecko
Člen | 20
+
0
-

config.neon

<?php
# WARNING: it is CRITICAL that this file & directory are NOT accessible directly via a web browser!
# https://nette.org/en/security-warning
#
parameters:


application:
	errorPresenter: Error
	mapping:
		*: App\*Module\Presenters\*Presenter


session:
	expiration: 14 days


services:
	- App\Model\UserManager
	- App\Forms\FormFactory
	- App\Forms\SignInFormFactory
	- App\Forms\SignUpFormFactory
	router: App\RouterFactory::createRouter

security:
    users:
        admin: secret  # user 'admin', password 'heslo'
?>

config-local.neon

<?php
parameters:


database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: root
	password:
	options:
		lazy: yes
?>

Editoval kotrvecko (9. 10. 2016 13:44)

kotrvecko
Člen | 20
+
0
-

Lexi napsal(a):

Ukaž tvůj config.neon a config.local.neon

Vím, že mé configy nestojí za nic, ale teprve začínám. :-D Kdyby se ti v nich něco nezdálo, tak si ráda nechám poradit. :-) Pro jistotu ještě posílám bootstrap.php.

<?php

require __DIR__ . '/../vendor/autoload.php';

$configurator = new Nette\Configurator;

//$configurator->setDebugMode('23.75.345.200'); // enable for your remote IP
$configurator->enableDebugger(__DIR__ . '/../log');

$configurator->setTimeZone('Europe/Prague');
$configurator->setTempDirectory(__DIR__ . '/../temp');

$configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->register();

$configurator->addConfig(__DIR__ . '/config/config.neon');
$configurator->addConfig(__DIR__ . '/config/config.local.neon');

$container = $configurator->createContainer();

return $container;
?>
ViPEr*CZ*
Člen | 818
+
0
-

Tohle ještě pošli: App\Model\UserManager

kotrvecko
Člen | 20
+
0
-

ViPErCZ napsal(a):

Tohle ještě pošli: App\Model\UserManager

V tom jsem ještě nic nedělala.

<?php

namespace App\Model;

use Nette;
use Nette\Security\Passwords;


/**
 * Users management.
 */
class UserManager implements Nette\Security\IAuthenticator
{
	use Nette\SmartObject;

	const
		TABLE_NAME = 'users',
		COLUMN_ID = 'id',
		COLUMN_NAME = 'username',
		COLUMN_PASSWORD_HASH = 'password',
		COLUMN_EMAIL = 'email',
		COLUMN_ROLE = 'role';


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


	public function __construct(Nette\Database\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([
				self::COLUMN_PASSWORD_HASH => Passwords::hash($password),
			]);
		}

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


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

}



class DuplicateNameException extends \Exception
{}
?>
Jan Mikeš
Člen | 771
+
+1
-

Už to vidím, nette se nelíbí to, že máš 2 implementace authenticatoru, jednu aktivuješ tím, že máš v configu sekci security a druhou, protože máš u tvého App\Model\UserManager implements Authenticator, buď tedy zruš to implements ..., nebo celou sekci security: z configu.

kotrvecko
Člen | 20
+
0
-

Lexi napsal(a):

Už to vidím, nette se nelíbí to, že máš 2 implementace authenticatoru, jednu aktivuješ tím, že máš v configu sekci security a druhou, protože máš u tvého App\Model\UserManager implements Authenticator, buď tedy zruš to implements ..., nebo celou sekci security: z configu.

Děkuji. Po zrušení implements v UserManager to házelo další chyby, tak jsem místo toho smazala security v configu. Akorát na to bylo napojeno celé přihlášení, které nefunguje, tak si s tím ještě zkusím pohrát.

kotrvecko
Člen | 20
+
0
-

kotrvecko napsal(a):

Lexi napsal(a):

Už to vidím, nette se nelíbí to, že máš 2 implementace authenticatoru, jednu aktivuješ tím, že máš v configu sekci security a druhou, protože máš u tvého App\Model\UserManager implements Authenticator, buď tedy zruš to implements ..., nebo celou sekci security: z configu.

Děkuji. Po zrušení implements v UserManager to házelo další chyby, tak jsem místo toho smazala security v configu. Akorát na to bylo napojeno celé přihlášení, které nefunguje, tak si s tím ještě zkusím pohrát.

Takže po smazání security v config.neon mám stále chybu odkazující na $container:

Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.
…\eds-www\nette-blog\app\bootstrap.php:20 source Nette\Configurator->createContainer()

<?php
10:    $configurator->setTimeZone('Europe/Prague');
11:    $configurator->setTempDirectory(__DIR__ . '/../temp');
12:
13:    $configurator->createRobotLoader()
14:        ->addDirectory(__DIR__)
15:        ->register();
16:
17:    $configurator->addConfig(__DIR__ . '/config/config.neon');
18:    $configurator->addConfig(__DIR__ . '/config/config.local.neon');
19:
20:    $container = $configurator->createContainer();
21:
22:    return $container;
?>
ViPEr*CZ*
Člen | 818
+
0
-

No píše to, že to nevidí tuto třídu: Class App\Model\UserManager
Zkus vymazat ještě cache jestli tato chyba stále zůstane.

Altimit
Člen | 82
+
0
-

to je v base app po nainstalování a já v tom problém nevidím..
Spíše toto: Chlape nepiš html do presenteru na to máš šablony..
viz toto:

<?php

    namespace App\Presenters;

    use Nette;
    use Nette\Application\UI\Form;


    class SignPresenter extends Nette\Application\UI\Presenter
    {
        <ul class="navig">
        <li><a n:href="Homepage:">Články</a></li>
        {if $user->loggedIn}
            <li><a n:href="Sign:out">Odhlásit</a></li>
        {else}
?>

podle mně se musíš podívat jak se to všechno píše.. tudíž projet dokumentaci, podívat se když tak na zdejší fórum.
pokud chceš mít tady tohle tak to se píše do html a.k.a. souborů .latte

<nav class="z-depth-4 cyan" role="navigation">
    <div class="nav-wrapper container">
        <ul class="hide-on-med-and-down">
            <li><a class="waves-effect"  href="/">Domů</a></li>
            <li><a class="waves-effect" href="{$presenter->link(':Front:Home:aboutus')}">O Projektu</a></li>
            <li><a class="waves-effect" href="{$presenter->link(':Front:Blog:default')}">Novinky</a></li>
            {if $user->loggedIn}
                <ul class="right hide-on-med-and-down">
                    {if $user->isInRole('admin')}<li><a class="waves-effect" href="#">Administrace</a></li>{else}{/if}
                    {if $user->isInRole('teacher')}<li><a class="waves-effect" href="{$presenter->link(':Teacher:Home:default')}">Učitelská sekce</a></li>{else}{/if}
                    <li><a class="waves-effect" href="{$presenter->link(':Class:Home:default')}">Třída</a></li>
                    <li><a class="waves-effect" href="#">Účet</a></li>
                    <li><a class="waves-effect" href="{$presenter->link(':Front:Sign:out')}">Odhlásit</a></li>
                </ul>
            {else}
                <ul class="right hide-on-med-and-down">
                    <li><a href="{$presenter->link(':Front:Sign:up')}">Registrovat</a></li>
                    <li><a href="{$presenter->link(':Front:Sign:in')}">Přihlásit</a></li>
                </ul>
            {/if}
        </ul>
        <ul id="nav-mobile" class="side-nav" style="transform: translateX(-100%);">
            <li><a id="logo-container" href="/" style="text-align:center;" class="cyan-text accent-4">Školní zápisy</a></li>
            <li class="divider"></li>
            <li>{control menu}</li>
            <li><a href="/">Domů</a></li>
            <li><a href="{$presenter->link(':Front:Home:aboutus')}">O Projektu</a></li>
            <li><a href="{$presenter->link(':Front:Blog:default')}">Novinky</a></li>
            <li class="divider"></li>
            {if $user->loggedIn}
                <li><a href="{$presenter->link(':Class:Home:default')}">Třída</a></li>
                <li><a href="#">Účet</a></li>
                <li><a href="{$presenter->link(':Front:Sign:out')}">Odhlásit</a></li>
            {else}
                <li><a href="{$presenter->link(':Front:Sign:in')}">Přihlást</a></li>
                <li><a href="{$presenter->link(':Front:Sign:up')}">Registrovat</a></li>
            {/if}
        </ul>
        <a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
    </div>
</nav>

toto mám v @menu.latte

kotrvecko
Člen | 20
+
0
-

ViPErCZ napsal(a):

No píše to, že to nevidí tuto třídu: Class App\Model\UserManager
Zkus vymazat ještě cache jestli tato chyba stále zůstane.

Ahoj, zkusila jsem vymazat cache v temp / cachce / Nette.Configurator, ale problém je stále stejný.

Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.

Na fóru jsem našla jen řešení vymazat v config.neon řádek v services: App\Model\UserManager a App\Forms\SignInFormFactory, což mi nepomohlo. Zkusila jsem vrátit všechny kroky z článku Autentifikace, ale už se té chyby nemůžu zbavit. Ráda bych porkačovala dál a zkusila vlastní autentifikátor, ale co s tou chybou?

Jan Mikeš
Člen | 771
+
0
-

No někde v configu registruješ službu App\Model\UserManager ale robot loader ji nedokáže najít, protože jsi tu třídu smazala.
Zkontrolu všechny .neon configy, jestli tam tu třídu nemáš zaregistrovanou, nebo jestli jiná zaregistrovaná služba tuto třídu nevyžaduje jako závislost. (konstruktory, inject..).
Pokud jsi si jistá, že třídu nehledáš, smazej pro jistotu ještě jednou cache (nestačí smazat Nette.Configurator, ale celou složku cache v adresáři temp).
Je velmi důležité číst chybové hlášky a pochopit co znamenají, pak můžeš systematicky postupovat a chybu hledat.

Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.
Jak jsem popisoval na začátku, Nette vytvořilo službu s názvem 27_App_Model_UserManager, v této službě se používá třída App\Model\UserManager ale Nette ji nemůže najít. Takže buď můžeš zrušit vytváření této služby, nebo si vytvořit (zpětně vrátit) tuto třídu.

kotrvecko
Člen | 20
+
0
-

Lexi napsal(a):

No někde v configu registruješ službu App\Model\UserManager ale robot loader ji nedokáže najít, protože jsi tu třídu smazala.
Zkontrolu všechny .neon configy, jestli tam tu třídu nemáš zaregistrovanou, nebo jestli jiná zaregistrovaná služba tuto třídu nevyžaduje jako závislost. (konstruktory, inject..).
Pokud jsi si jistá, že třídu nehledáš, smazej pro jistotu ještě jednou cache (nestačí smazat Nette.Configurator, ale celou složku cache v adresáři temp).
Je velmi důležité číst chybové hlášky a pochopit co znamenají, pak můžeš systematicky postupovat a chybu hledat.

Class App\Model\UserManager used in service ‚27_App_Model_UserManager‘ not found.
Jak jsem popisoval na začátku, Nette vytvořilo službu s názvem 27_App_Model_UserManager, v této službě se používá třída App\Model\UserManager ale Nette ji nemůže najít. Takže buď můžeš zrušit vytváření této služby, nebo si vytvořit (zpětně vrátit) tuto třídu.

Ahoj Lexi, ráda tě tu vidím. Jelikož mám málo času, tak jsem přistoupila k radikálnímu řešení a smazala celý projekt a jdu od začátku. Tohle však nemůžu dělat pořád, když už budu s projektem dál. Jak píšeš, musím se naučit pochopit chybové hlášky. Autentifikaci v quickstartu už vynechám a zkusím udělat vlastní autentifikátor podle článku Přihlašování a oprávnění. Snad nenarazím na stejnou chybu s UserManagerem.

Když už tě tu mám, tak mi určitě poradíš s požadavky z checker, protože nechci narážet na zbytečné chyby. Vykřičník mám u Fileinfo extension, PDO SQLite extension, Memcache extension, Fileinfo extension or mime_content_type() a Intl extension. Jak to můžu opravit? :-)

Mysteria
Člen | 797
+
0
-

Musíš si povolit potřebná rozšíření pro PHPčko. Konfiguraci najdeš v souboru PHP.ini (bude tam, kam jsi si nainstaloval PHP).
Zajímá tě tahle část, kdy středník na začátku řádku znamená, že je rozšíření zakázáno:

;extension=php_bz2.dll
extension=php_curl.dll
extension=php_fileinfo.dll
extension=php_gd2.dll
;extension=php_gettext.dll
;extension=php_gmp.dll
;extension=php_intl.dll
;extension=php_imap.dll
;extension=php_interbase.dll
;extension=php_ldap.dll
extension=php_mbstring.dll
;extension=php_exif.dll      ; Must be after mbstring as it depends on it
;extension=php_mysql.dll
extension=php_mysqli.dll
;extension=php_oci8_12c.dll  ; Use with Oracle Database 12c Instant Client
extension=php_openssl.dll
;extension=php_pdo_firebird.dll
extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
;extension=php_pdo_odbc.dll
;extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
;extension=php_pgsql.dll
;extension=php_pspell.dll
;extension=php_shmop.dll
extension=php_ftp.dll

Stačí smazat středníky před požadovanými rozšířeními, na které Checker upozorňuje a restartovat web server.

Jan Mikeš
Člen | 771
+
0
-

@kotrvecko memcache extension pravděpodobně potřebovat nebudeš, takže zrovna tuhle extension můžeš ignorovat. Fileinfo ti pomůže při uploadování souborů a PDO SQLite je pro sqlite databáze (to se může hodit, některé samostatné balíčky sqlite využívají).

kotrvecko
Člen | 20
+
0
-

Děkuji, akorát jsem nenašla rozšíření pro „Memcache extension“ a u „Intl extension“ mám chybovou hlášku při spuštění web serveru: Program nelze spustit, protože v počítači chybí icuuc56.dll. Pokuste se tento problém vyřešit přeinstalací programu.

Jan Mikeš
Člen | 771
+
+1
-

@kotrvecko na windowsu je to s instalací trošku komplikovanější, každopádně jak jsem psal, bez memcache se 100% obejdeš a intl obsahuje sadu funkcí pro práci s cizojazyčnými funkcemi atd. takže pokud se nechystáš například konvertovat azbuku pomocí webalize() tak ti toto rozšíření chybět nebude.

kotrvecko
Člen | 20
+
0
-

Díky za rady. Jdu si s tím zase hrát. :-)

Mirek
Člen | 86
+
0
-

K té chybě, že chybí icuuc56.dll – v adresáři PHP by mělo být celkem asi 8 souborů, začínající na icu, tak všechny tyhle soubory nakopíruj do adresáře apache/bin (adresář apache se může jmenovat i jinak, např apache24) a restartuj webserver

n.u.r.v.
Člen | 485
+
0
-

Lexi napsal(a):

@kotrvecko memcache extension pravděpodobně potřebovat nebudeš, takže zrovna tuhle extension můžeš ignorovat. Fileinfo ti pomůže při uploadování souborů a PDO SQLite je pro sqlite databáze (to se může hodit, některé samostatné balíčky sqlite využívají).

Nevyžaduje náhodou nette PDO SQLite pro cache? Tedy je to „povinné“?

Jan Mikeš
Člen | 771
+
0
-

@n.u.r.v. pokud se jedná o závislost, bez které se nette nerozjede, checker by napsal že nejsou splněny minimální požadavky. Nejsem si tím 100% jist, takže možná plácám teď hlouposti, ale zdá se mi, že bez sqlite nette funguje.

Editoval Lexi (17. 10. 2016 12:11)

kotrvecko
Člen | 20
+
0
-

Můžu nějak kompletně odstranit UserManager? Kde všude figuruje?

Jan Mikeš
Člen | 771
+
0
-

@kotrvecko tam kde ho používáš – nette ho nijak nepotřebuje, musíš tedy zkontrolovat tebou vytvořené závislosti, předpokládám, že bude použit asi v authenticatoru.

kotrvecko
Člen | 20
+
0
-

Jan Mikeš napsal(a):

@kotrvecko tam kde ho používáš – nette ho nijak nepotřebuje, musíš tedy zkontrolovat tebou vytvořené závislosti, předpokládám, že bude použit asi v authenticatoru.

A když si např. udělám nový sandbox, tak ho odstraním jak? :-)