Authenticator s dibi přes modelLoader

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

Zdravím, mám takový problém. Používám dibi a pro jednodušší připojování k tabulkám jsem použil model loader viz:
https://pla.nette.org/…cy-injection

Vytvořil jsem si class na registrační formulář a chci aby se po úspěšné registraci uživatel automaticky přihlásil. Jenže nevím, jak se dostat k autentizaci. Kvůli dibi jsem si hodil i požadovaný namespace nad třídu Authenticator. Zkoušel jsem to dosti způsoby, ale u základního mi to háže:
Cannot instantiate service, class ‚Models\Authenticator‘ not found.

Když se k tomu připojím pomocí getModel, tak mi to zase cpe, že metoda getUser neexistuje.

RegistrationForm

<?php
namespace FrontModule\Forms;

use Nette\Application\UI\Form,
    Nette\InvalidStateException,
    Nette\Security as NS;

class RegistrationForm extends Form {

    public function __construct($parent = null, $name = null) {
        parent::__construct($parent, $name);

        $this->addProtection('Prosím pdešlete formulář znovu (vypršela platnost bezpečnostního tokenu).');

        $this->addText('email', 'Email:')
                ->addRule(Form::FILLED, 'Prosím zadejte registrační email')
                ->addRule(Form::EMAIL, 'Zadaný email je neplatný');

        $this->addSubmit('send', 'Zaregistrovat se');
        $this->onSuccess[] = array($this, 'submitted');
    }

    public function submitted(Form $form) {
        try {
            $values = $form->values;
            $values['ip'] = $this->presenter->getService('httpRequest')->getRemoteAddress();
            $values['regdate'] = new \Nette\Datetime;
            $values['salt'] = $this->presenter->context->params['salt'];
            $password = $this->presenter->getModel('user')->userCreate($values);


            $this->presenter->getUser()->setExpiration('+ 20 minutes', TRUE);
            $this->presenter->getUser()->login($values->email, $password);

            $this->presenter->flashMessage('Účet byl úspěšně vytvořen a vy úspěšně přihlášeni', 'success');
            $this->presenter->redirect('Homepage:');
        } catch (InvalidStateException $e) {
            $this->presenter->flashMessage($e->getMessage(), 'warning');
            $this->presenter->redirect('this');
        }
    }

}

Authenticator

<?php
namespace Model;
use Nette\Security as NS;

class Authenticator extends \Nette\Object implements NS\IAuthenticator {

    /** @var DibiConnection */
    private $db;

    public function __construct($connection, $config) {
        $this->db = $connection;
    }

    /**
     * Performs an authentication
     * @param  array
     * @return Nette\Security\Identity
     * @throws Nette\Security\AuthenticationException
     */
    public function authenticate(array $credentials) {
        list($email, $password) = $credentials;
        $row = $this->db
                ->select('*')
                ->from('user')
                ->where('email', $email)
                ->fetch();

        if (!$row || ($row->password !== $this->calculateHash($password))) {
            throw new NS\AuthenticationException("Uživatel '$email' nebyl nalezen.", self::IDENTITY_NOT_FOUND);
        }

        unset($row->password);
        return new NS\Identity($row->id, $row->role, $row->toArray());
    }

    /**
     * Computes salted password hash.
     * @param  string
     * @return string
     */
    public function calculateHash($password) {
        return hash('sha256', $password . $this->context->params['salt']);
    }

}

Děkuji za rady

umrlec
Člen | 56
+
0
-

Ten Authenticator máš v namespace Model a chyba ti hlásí, že neexistuje třída ModelS\Authenticator. Že by překlep v configu?

Jack06
Člen | 168
+
0
-

Ok fajne, překlep v configu byl, nicméně teď to hodí:

Missing argument 1 for Model\Authenticator::__construct(), called in C:\xampp\htdocs\zapisto\libs\Nette\DI\ServiceBuilder.php on line 49 and defined

u constructu na dibi, nevím jak, ale asi to bude potřeba prohnat tim modelLoaderem. Jako DI je pro mě celkem novinka, takže se v tom učím a fakt netuším jestli se to dá nastavit i nějak v neonu, nebo ne.

umrlec
Člen | 56
+
0
-

Ukaž ten config …

Jack06
Člen | 168
+
0
-
common:
        php: # PHP configuration
            date.timezone: Europe/Prague
            # session.save_path: "%tempDir%/sessions"
            # zlib.output_compression: yes

        database:
            hostname: 127.0.0.1
            username: root
            password:
            database: db_xx
            persistent: true
            charset: utf8
            lazy: true

        services:
            robotLoader:
                run: true

            authenticator:
                Model\Authenticator

            modelLoader:
                factory: ModelLoader::factory

        variables:
            salt: xxx

production < common:

development < common:

console < common:
umrlec
Člen | 56
+
0
-

Zkus to takto …

config

common:
        php: # PHP configuration
            date.timezone: Europe/Prague
            # session.save_path: "%tempDir%/sessions"
            # zlib.output_compression: yes

        services:
		robotLoader:
                	run: true

		modelLoader:
                	factory: ModelLoader::factory

		authenticator:
			class: Model\Authenticator
			arguments: ["@database"]

		database:
			class: DibiConnection
			arguments: [ {
				hostname: 127.0.0.1
				username: root
				password: ''
				database: db_xx
				persistent: true
				charset: utf8
				lazy: true
			} ]

        variables:
            salt: xxx

production < common:

development < common:

console < common:

A v konstruktoru Authenticatoru si smaž ten druhý parametr

umrlec
Člen | 56
+
0
-

Byla tu i lepší odpověď, ale její autor jí smazal. :/

Jack06
Člen | 168
+
0
-

No, tím ale nebude fungovat modelLoader, respektive toto:

class ModelLoader {
        private $connection;
        private $config;

        public static function factory(Nette\DI\Container $container) {
                $config = $container->params['database']; // toto
                $db = dibi::connect($config);
                return new self($db, $config);
        }

        public function __construct($connection, $config) {
                $this->connection = $connection;
                $this->config = $config;
        }

        public function loadModel($modelName) {
                $class = "Model\\$modelName";
                return new $class($this->connection, $this->config);
        }
}
vranacik
Člen | 9
+
0
-

a čo schovávaš do $config?, nie je ten parameter zbytočný? Inač som si prvý krát prešiel odkaz, ktorý máš v prvom poste a je to tam celkom slušne vysvetlené a umrlec ti radí tiež dobre.

ak v $config prenášaš konfiguráciu pre pripojenie k DB tak načo to máš aj v neone? Presiel som si to tri krát a nejak som tomu nepochopil (tomu tvojmu kodu)

//ziskavaš z kontainera, tak načo ho potrebuješ pchať aj do konštruktora?
$config = $container->params['database'];
//v kontajneri tie dáta najdeš vždy
...
//a vo factory by potom malo stačiť vrátiť len spojenie, teda:
return $db
Jack06
Člen | 168
+
0
-

Ten ModelLoader mi byl takto nahozen, už nevím kdo mi to poslal, nicméně jelikož jsem nechápal jak s tím DI ruku v ruce pracovat, tak jsem to prostě použil tak, jak mi to někdo napsal. Ano ten parametr je zbytečný. Bylo mi posláno již funkční řešení. Pokud by měl někdo stejný problém, tak: https://gist.github.com/1076590