Commit eb34b9aa authored by Martin Gregor's avatar Martin Gregor
Browse files

Initial commit

Order Allow,Deny
Deny from all
// Load Nette Framework or autoloader generated by Composer
require __DIR__ . '/../vendor/autoload.php';
$configurator = new Nette\Config\Configurator;
// Enable Nette Debugger for error visualisation & logging
$configurator->enableDebugger(__DIR__ . '/../log');
// Specify folder for cache
$configurator->setTempDirectory(__DIR__ . '/../temp');
// Enable RobotLoader - this will load all classes automatically
->addDirectory(__DIR__ . '/../vendor/others')
// Create Dependency Injection container from config.neon file
$configurator->addConfig(__DIR__ . '/config/config.neon');
$configurator->addConfig(__DIR__ . '/config/config.local.neon', $configurator::NONE); // none section
$container = $configurator->createContainer();
return $container;
# SECURITY WARNING: it is CRITICAL that this file & directory are NOT accessible directly via a web browser!
# If you don't protect this directory from direct web access, anybody will be able to see your passwords.
date.timezone: Europe/Prague
# zlib.output_compression: yes
errorPresenter: Error
dsn: 'mysql:host=localhost;dbname=test'
expiration: 14 days
authenticator: Authenticator
routerFactory: RouterFactory
router: @routerFactory::createRouter
production < common:
development < common:
use Nette\Security,
* Users authenticator.
class Authenticator extends Nette\Object implements Security\IAuthenticator
TABLE_NAME = 'users',
COLUMN_ID = 'id',
COLUMN_NAME = 'username',
COLUMN_PASSWORD = 'password',
COLUMN_ROLE = 'role',
/** @var Nette\Database\Connection */
private $database;
public function __construct(Nette\Database\Connection $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 Security\AuthenticationException('The username is incorrect.', self::IDENTITY_NOT_FOUND);
} elseif (!self::verifyPassword($password, $row[self::COLUMN_PASSWORD])) {
throw new Security\AuthenticationException('The password is incorrect.', self::INVALID_CREDENTIAL);
$arr = $row->toArray();
return new Nette\Security\Identity($row[self::COLUMN_ID], $row[self::COLUMN_ROLE], $arr);
* Computes salted password hash.
* @param string
* @return string
public static function hashPassword($password, $options = NULL)
if ($password === Strings::upper($password)) { // perhaps caps lock is on
$password = Strings::lower($password);
$password = substr($password, 0, self::PASSWORD_MAX_LENGTH);
$options = $options ?: implode('$', array(
'algo' => '$2a', // blowfish
'cost' => '07',
'salt' => Strings::random(22),
return crypt($password, $options);
* Verifies that a password matches a hash.
* @return bool
public static function verifyPassword($password, $hash)
return self::hashPassword($password, $hash) === $hash
|| (PHP_VERSION_ID >= 50307 && substr($hash, 0, 3) === '$2a' && self::hashPassword($password, $tmp = '$2x' . substr($hash, 3)) === $tmp);
* Base presenter for all application presenters.
abstract class BasePresenter extends Nette\Application\UI\Presenter
use Nette\Diagnostics\Debugger;
* Error presenter.
class ErrorPresenter extends BasePresenter
* @param Exception
* @return void
public function renderDefault($exception)
if ($this->isAjax()) { // AJAX request? Just note this error in payload.
$this->payload->error = TRUE;
} elseif ($exception instanceof Nette\Application\BadRequestException) {
$code = $exception->getCode();
// load template 403.latte or 404.latte or ... 4xx.latte
$this->setView(in_array($code, array(403, 404, 405, 410, 500)) ? $code : '4xx');
// log to access.log
Debugger::log("HTTP code $code: {$exception->getMessage()} in {$exception->getFile()}:{$exception->getLine()}", 'access');
} else {
$this->setView('500'); // load template 500.latte
Debugger::log($exception, Debugger::ERROR); // and log exception
* Homepage presenter.
class HomepagePresenter extends BasePresenter
public function renderDefault()
$this->template->anyVariable = 'any value';
use Nette\Application\UI;
* Sign in/out presenters.
class SignPresenter extends BasePresenter
* Sign-in form factory.
* @return Nette\Application\UI\Form
protected function createComponentSignInForm()
$form = new UI\Form;
$form->addText('username', 'Username:')
->setRequired('Please enter your username.');
$form->addPassword('password', 'Password:')
->setRequired('Please enter your password.');
$form->addCheckbox('remember', 'Keep me signed in');
$form->addSubmit('send', 'Sign in');
// call method signInFormSucceeded() on success
$form->onSuccess[] = $this->signInFormSucceeded;
return $form;
public function signInFormSucceeded($form)
$values = $form->getValues();
if ($values->remember) {
$this->getUser()->setExpiration('14 days', FALSE);
} else {
$this->getUser()->setExpiration('20 minutes', TRUE);
try {
$this->getUser()->login($values->username, $values->password);
} catch (Nette\Security\AuthenticationException $e) {
public function actionOut()
$this->flashMessage('You have been signed out.');
use Nette\Application\Routers\RouteList,
* Router factory.
class RouterFactory
* @return Nette\Application\IRouter
public function createRouter()
$router = new RouteList();
$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
return $router;
* My Application layout template.
* @param string $basePath web base path
* @param string $robots tell robots how to index the content of a page (optional)
* @param array $flashes flash messages
<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="robots" content="{$robots}" n:ifset="$robots">
<title>{block title|striptags|upper}Nette Application Skeleton{/block}</title>
<link rel="stylesheet" media="screen,projection,tv" href="{$basePath}/css/screen.css">
<link rel="stylesheet" media="print" href="{$basePath}/css/print.css">
<link rel="shortcut icon" href="{$basePath}/favicon.ico">
{block head}{/block}
<script> document.documentElement.className+=' js' </script>
<div n:foreach="$flashes as $flash" class="flash {$flash->type}">{$flash->message}</div>
{include #content}
{block scripts}
<script src="{$basePath}/js/jquery.js"></script>
<script src="{$basePath}/js/netteForms.js"></script>
<script src="{$basePath}/js/main.js"></script>
{var $robots = noindex}
{block content}
<h1 n:block=title>Access Denied</h1>
<p>You do not have permission to view this page. Please try contact the web
site administrator if you believe you should be able to view this page.</p>
<p><small>error 403</small></p>
{var $robots = noindex}
{block content}
<h1 n:block=title>Page Not Found</h1>
<p>The page you requested could not be found. It is possible that the address is
incorrect, or that the page no longer exists. Please use a search engine to find
what you are looking for.</p>
<p><small>error 404</small></p>
{var $robots = noindex}
{block content}
<h1 n:block=title>Method Not Allowed</h1>
<p>The requested method is not allowed for the URL.</p>
<p><small>error 405</small></p>
{var $robots = noindex}
{block content}
<h1 n:block=title>Page Not Found</h1>
<p>The page you requested has been taken off the site. We apologize for the inconvenience.</p>
<p><small>error 410</small></p>
{var $robots = noindex}
{block content}
<h1 n:block=title>Oops...</h1>
<p>Your browser sent a request that this server could not understand or process.</p>
{layout none}
<!DOCTYPE html>
<meta charset="utf-8">
<meta name="robots" content="noindex">
body { color: #333; background: white; width: 500px; margin: 100px auto }
h1 { font: bold 47px/1.5 sans-serif; margin: .6em 0 }
p { font: 21px/1.5 Georgia,serif; margin: 1.5em 0 }
small { font-size: 70%; color: gray }
<h1>Server Error</h1>
<p>We're sorry! The server encountered an internal error and
was unable to complete your request. Please try again later.</p>
<p><small>error 500</small></p>
This diff is collapsed.
{var $robots = noindex}
{block content}
<h1 n:block=title>Sign in</h1>
{control signInForm}
{* or use {include '../components/form.latte', form => signInForm} *}
{form $form}
<ul class=error n:if="$form->errors">
<li n:foreach="$form->errors as $error">{$error}</li>
<tr n:foreach="$form->controls as $input" n:class="$input->required ? required">
<th>{if $input->controlPrototype->type !== checkbox}{label $input /}{/if}</th>
<td>{input $input} {if $input->controlPrototype->type === checkbox}{label $input /}{/if}
<span class=error n:if="$input->errors">{$input->errors|implode:' '}</span>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment