You say 'a step backwards', I say 'modern web development'.

This commit is contained in:
flash 2018-03-14 02:39:02 +01:00
parent f57b58b212
commit 7a160c1e3e
15 changed files with 114 additions and 198 deletions

View file

@ -11,7 +11,6 @@
"ext-bcmath": "*",
"ext-mbstring": "*",
"twig/twig": "~2.4",
"phroute/phroute": "~2.1",
"nesbot/carbon": "~1.22",
"illuminate/database": "~5.5",
"illuminate/filesystem": "~5.5",

46
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "ad8d5aadca5a1f854d58dd82131f701a",
"content-hash": "bfc5b8cbdbf22514c4b51ae1af8c333b",
"packages": [
{
"name": "composer/ca-bundle",
@ -1148,50 +1148,6 @@
],
"time": "2018-03-10T10:10:14+00:00"
},
{
"name": "phroute/phroute",
"version": "v2.1.0",
"source": {
"type": "git",
"url": "https://github.com/mrjgreen/phroute.git",
"reference": "dbe2b986f9ee1dd33dc956fcc35d1fa22e8e196c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mrjgreen/phroute/zipball/dbe2b986f9ee1dd33dc956fcc35d1fa22e8e196c",
"reference": "dbe2b986f9ee1dd33dc956fcc35d1fa22e8e196c",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "*",
"satooshi/php-coveralls": "dev-master"
},
"type": "library",
"autoload": {
"psr-4": {
"Phroute\\Phroute\\": "src/Phroute"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Joe Green",
"email": "joe.green.0991@gmail.com"
}
],
"description": "Fast, fully featured restful request router for PHP",
"keywords": [
"router",
"routing"
],
"time": "2015-07-22T20:46:43+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",

View file

@ -8,3 +8,13 @@ $app = Application::start(
IO\Directory::exists(__DIR__ . '/vendor/phpunit/phpunit')
);
$app->startDatabase();
if (PHP_SAPI !== 'cli') {
if (isset($_COOKIE['msz_uid'], $_COOKIE['msz_sid'])) {
$app->startSession((int)$_COOKIE['msz_uid'], $_COOKIE['msz_sid']);
}
//ob_start('ob_gzhandler');
$app->startTemplating();
}

View file

@ -1,6 +1,4 @@
<?php
namespace Misuzu\Controllers;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Misuzu\Application;
@ -9,9 +7,9 @@ use Misuzu\Net\IP;
use Misuzu\Users\User;
use Misuzu\Users\Session;
class AuthController extends Controller
{
private const USERNAME_VALIDATION_ERRORS = [
require_once __DIR__ . '/../misuzu.php';
$username_validation_errors = [
'trim' => 'Your username may not start or end with spaces!',
'short' => "Your username is too short, it has to be at least " . User::USERNAME_MIN_LENGTH . " characters!",
'long' => "Your username is too long, it can't be longer than " . User::USERNAME_MAX_LENGTH . " characters!",
@ -20,21 +18,38 @@ class AuthController extends Controller
'spacing' => 'Please use either underscores or spaces, not both!',
];
public function login()
{
$app = Application::getInstance();
$mode = $_GET['m'] ?? 'login';
$app->templating->var('auth_mode', $mode);
switch ($mode) {
case 'logout':
if ($app->getSession() === null) {
echo "You aren't logged in.";
} else {
echo "You've been logged out.";
set_cookie_m('uid', '', -3600);
set_cookie_m('sid', '', -3600);
$app->getSession()->delete();
$app->setSession(null);
}
echo '<meta http-equiv="refresh" content="1; url=/">';
break;
case 'login':
if ($app->getSession() !== null) {
return '<meta http-equiv="refresh" content="0; url=/">';
echo '<meta http-equiv="refresh" content="0; url=/">';
break;
}
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$twig = $app->templating;
return $twig->render('auth.login');
echo $app->templating->render('auth.login');
break;
}
if (!isset($_POST['username'], $_POST['password'])) {
return ['error' => "You didn't fill all the forms!"];
echo json_encode_m(['error' => "You didn't fill all the forms!"]);
break;
}
$username = $_POST['username'] ?? '';
@ -43,17 +58,19 @@ class AuthController extends Controller
try {
$user = User::where('username', $username)->orWhere('email', $username)->firstOrFail();
} catch (ModelNotFoundException $e) {
return ['error' => 'Invalid username or password!'];
echo json_encode_m(['error' => 'Invalid username or password!']);
break;
}
if (!$user->validatePassword($password)) {
return ['error' => 'Invalid username or password!'];
echo json_encode_m(['error' => 'Invalid username or password!']);
break;
}
$session = Session::createSession($user, 'Misuzu T1');
$session = Session::createSession($user, 'Misuzu T2');
$app->setSession($session);
$this->setCookie('uid', $session->user_id, 604800);
$this->setCookie('sid', $session->session_key, 604800);
set_cookie_m('uid', $session->user_id, 604800);
set_cookie_m('sid', $session->session_key, 604800);
// Temporary key generation for chat login.
// Should eventually be replaced with a callback login system.
@ -65,42 +82,30 @@ class AuthController extends Controller
setcookie('msz_tmp_id', $user->user_id, time() + 604800, '/', '.flashii.net');
setcookie('msz_tmp_key', $user->user_chat_key, time() + 604800, '/', '.flashii.net');
return ['error' => 'You are now logged in!', 'next' => '/'];
}
private function setCookie(string $name, string $value, int $expires): void
{
setcookie(
"msz_{$name}",
$value,
time() + $expires,
'/',
'',
!empty($_SERVER['HTTPS']),
true
);
}
public function register()
{
$app = Application::getInstance();
$prevent_registration = $app->config->get('Auth', 'prevent_registration', 'bool', false);
echo json_encode_m(['error' => 'You are now logged in!', 'next' => '/']);
break;
case 'register':
if ($app->getSession() !== null) {
return '<meta http-equiv="refresh" content="0; url=/">';
}
$prevent_registration = $app->config->get('Auth', 'prevent_registration', 'bool', false);
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$app->templating->var('prevent_registration', $prevent_registration);
return $app->templating->render('auth.register');
echo $app->templating->render('auth.register');
break;
}
if ($prevent_registration) {
return ['error' => 'Registration is not allowed on this instance.'];
echo json_encode_m(['error' => 'Registration is not allowed on this instance.']);
break;
}
if (!isset($_POST['username'], $_POST['password'], $_POST['email'])) {
return ['error' => "You didn't fill all the forms!"];
echo json_encode_m(['error' => "You didn't fill all the forms!"]);
break;
}
$username = $_POST['username'] ?? '';
@ -109,55 +114,42 @@ class AuthController extends Controller
$email = $_POST['email'] ?? '';
if ($username_validate !== '') {
return ['error' => self::USERNAME_VALIDATION_ERRORS[$username_validate]];
echo json_encode_m(['error' => $username_validation_errors[$username_validate]]);
break;
}
try {
$existing = User::where('username', $username)->firstOrFail();
if ($existing->user_id > 0) {
return ['error' => 'This username is already taken!'];
echo json_encode_m(['error' => 'This username is already taken!']);
break;
}
} catch (ModelNotFoundException $e) {
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL) || !check_mx_record($email)) {
return ['error' => 'The e-mail address you entered is invalid!'];
echo json_encode_m(['error' => 'The e-mail address you entered is invalid!']);
break;
}
try {
$existing = User::where('email', $email)->firstOrFail();
if ($existing->user_id > 0) {
return ['error' => 'This e-mail address has already been used!'];
echo json_encode_m(['error' => 'This e-mail address has already been used!']);
break;
}
} catch (ModelNotFoundException $e) {
}
if (password_entropy($password) < 32) {
return ['error' => 'Your password is considered too weak!'];
echo json_encode_m(['error' => 'Your password is too weak!']);
break;
}
User::createUser($username, $password, $email);
return ['error' => 'Welcome to Flashii! You may now log in.', 'next' => '/auth/login'];
}
public function logout()
{
$app = Application::getInstance();
$session = $app->getSession();
if ($session === null) {
echo "You aren't logged in.";
} else {
echo "You've been logged out.";
$this->setCookie('uid', '', -3600);
$this->setCookie('sid', '', -3600);
$session->delete();
$app->setSession(null);
}
return '<meta http-equiv="refresh" content="1; url=/">';
}
echo json_encode_m(['error' => 'Welcome to Flashii! You may now log in.', 'next' => '/auth.php?m=login']);
break;
}

View file

@ -1,24 +1,4 @@
<?php
namespace Misuzu;
use Phroute\Phroute\Dispatcher;
require_once __DIR__ . '/../misuzu.php';
//ob_start('ob_gzhandler');
$app = Application::getInstance();
if (isset($_COOKIE['msz_uid'], $_COOKIE['msz_sid'])) {
$app->startSession((int)$_COOKIE['msz_uid'], $_COOKIE['msz_sid']);
}
$app->startRouter();
$app->startTemplating();
include __DIR__ . '/../routes.php';
echo (new Dispatcher($app->router->getData()))->dispatch(
$_SERVER['REQUEST_METHOD'],
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
);
echo $app->templating->render('home.landing');

9
public/profile.php Normal file
View file

@ -0,0 +1,9 @@
<?php
use Misuzu\Users\User;
require_once __DIR__ . '/../misuzu.php';
$user_id = (int)$_GET['u'];
$app->templating->vars(['profile' => User::findOrFail($user_id)]);
echo $app->templating->render('user.view');

View file

@ -3,7 +3,6 @@ namespace Misuzu;
use Misuzu\Config\ConfigManager;
use Misuzu\Users\Session;
use Phroute\Phroute\RouteCollector;
use UnexpectedValueException;
use InvalidArgumentException;
@ -124,7 +123,6 @@ class Application extends ApplicationBase
$twig->addFunction('byte_symbol');
$twig->addFunction('session_id');
$twig->addFunction('config', [$this->config, 'get']);
$twig->addFunction('route', [$this->router, 'route']);
$twig->addFunction('git_hash', [Application::class, 'gitCommitHash']);
$twig->addFunction('git_branch', [Application::class, 'gitBranch']);
@ -132,16 +130,4 @@ class Application extends ApplicationBase
$twig->addPath('nova', __DIR__ . '/../views/nova');
}
/**
* Sets up the router module.
*/
public function startRouter(): void
{
if ($this->hasRouter) {
throw new UnexpectedValueException('Router module has already been started.');
}
$this->addModule('router', new RouteCollector);
}
}

View file

@ -1,6 +0,0 @@
<?php
namespace Misuzu\Controllers;
abstract class Controller
{
}

View file

@ -1,16 +0,0 @@
<?php
namespace Misuzu\Controllers;
use Misuzu\Application;
use Misuzu\Database;
class HomeController extends Controller
{
public function index(): string
{
$app = Application::getInstance();
$twig = $app->templating;
return $twig->render('home.landing');
}
}

View file

@ -1,16 +0,0 @@
<?php
namespace Misuzu\Controllers;
use Misuzu\Application;
use Misuzu\Users\User;
class UserController extends Controller
{
public function view(int $userId): string
{
$app = Application::getInstance();
$twig = $app->templating;
$twig->vars(['profile' => User::findOrFail($userId)]);
return $twig->render('user.view');
}
}

View file

@ -16,6 +16,28 @@ if (!function_exists('ends_with')) {
}
}
function json_encode_m($obj): string
{
if (!headers_sent()) {
header('Content-Type: application/json; charset=utf-8');
}
return json_encode($obj);
}
function set_cookie_m(string $name, string $value, int $expires): void
{
setcookie(
"msz_{$name}",
$value,
time() + $expires,
'/',
'',
!empty($_SERVER['HTTPS']),
true
);
}
function password_entropy(string $password): int
{
return count(count_chars(utf8_decode($password), 1)) * log(256, 2);

View file

@ -9,7 +9,7 @@
{% block content %}
<div class="platform form" id="auth-form">
<div>
<a href="{{ route('auth.register') }}"><button class="button" type="button">Click here if you don't have an account yet</button></a>
<a href="/auth.php?m=register"><button class="button" type="button">Click here if you don't have an account yet</button></a>
</div>
<div>
<input class="form__text" type="text" name="username" placeholder="Username">

View file

@ -37,7 +37,7 @@
function authfSubmit()
{
authHttp.open('POST', location.pathname, true);
authHttp.open('POST', location.pathname + '?m={{ auth_mode }}', true);
authHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
authHttp.send(authfForms());
}

View file

@ -6,8 +6,8 @@
<div class="landing__inner">
{% if app.session is null %}
<div class="landing__buttons">
<a href="{{ route('auth.register') }}" class="landing__button">register</a>
<a href="{{ route('auth.login') }}" class="landing__button">login</a>
<a href="/auth.php?m=register" class="landing__button">register</a>
<a href="/auth.php?m=login" class="landing__button">login</a>
</div>
<div class="landing__text">
<p>Keep an eye on <a href="https://twitter.com/flashiinet" class="container__footer-link" target="_blank" rel="noreferrer noopener">Twitter</a>!</p>

View file

@ -16,13 +16,13 @@
<nav class="header">
<div class="header__inner">
<div class="header__navigation">
<a class="header__entry fa-home" href="/">home</a> {# for whatever backwards reason {{ route('main.index') }} doesn't do anything here #}
<a class="header__entry fa-home" href="/">home</a>
<a class="header__entry fa-comments" href="https://chat.flashii.net">chat</a>
{% if app.session is not null %}
<a class="header__entry fa-sign-out" href="{{ route('auth.logout') }}">logout</a>
<a class="header__entry fa-sign-out" href="/auth.php?m=logout">logout</a>
{% endif %}
</div>
<a class="header__user" href="{{ app.session is not null ? route('users.view', [app.session.user_id]) : route('auth.register') }}">
<a class="header__user" href="{{ app.session is not null ? '/profile.php?u=' ~ app.session.user_id : '/auth.php?m=login' }}">
<div class="header__username">{{ app.session is not null ? app.session.user.username : 'login' }}</div>
<div class="header__avatar" style="background-image: url('https://static.flash.moe/images/{{ app.session is not null ? 'discord-logo' : 'nova-none' }}.png')"></div>
</a>