neotel-apply/lib/IndexController.php

143 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
namespace NeotelApply;
use ix\HookMachine;
use ix\Controller\Controller;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Exception\HttpInternalServerErrorException;
class IndexController extends Controller {
/**
* @param Request $request The Request object
* @param Response $response The Response object
* @param mixed[] $args Arguments passed from the router (if any)
* @return Response The resulting Response object
*/
public function requestGET(Request $request, Response $response, ?array $args = []): Response {
$session = $this->container->get('session')->ensure_create()->retrieve();
if (!array_key_exists('numbers', $session->session_data)) {
$session->session_data['numbers'] = implode(',', [
random_int(1, 9),
random_int(1, 9),
]);
}
$numbers = array_map((function($i) { return intval($i); }), explode(',', $session->session_data['numbers']));
$csrf_token = $this->container->get('csrf')->generate('csrf');
$html = $this->container->get('html');
$messageBanner = null;
if (array_key_exists('message', $args)) {
$messageBanner = $html->tagHasChildren('div', ['class' => 'message'], $args['message']);
}
$response->getBody()->write($html->renderDocument(
[
$html->tag('meta', ['charset' => 'utf-8']),
$html->tag('meta', ['name' => 'viewport', 'content' => 'initial-scale=1, width=device-width']),
$html->tag('link', ['rel' => 'stylesheet', 'href' => 'styles.css']),
$html->tagHasChildren('title', [], 'register for tel.tilde.org.nz'),
],
[
$html->tagHasChildren('main', [], ...[
$html->tagHasChildren('h1', [], ...[
'register for ',
$html->tagHasChildren('a', ['href' => 'https://tel.tilde.org.nz'], 'tel.tilde.org.nz'),
]),
$messageBanner ?? '',
$html->tagHasChildren('p', [], ...[
"If you previously had a tilde.tel extension, please mention that in your application!",
]),
$html->tagHasChildren('form', ['class' => 'form', 'method' => 'POST'], ...[
$html->tag('input', ['type' => 'hidden', 'name' => '_csrf', 'value' => strval($csrf_token)]),
$html->tagHasChildren('label', ['for' => 'username'], 'Username (required)'),
$html->tag('input', ['id' => 'username', 'name' => 'username', 'type' => 'text', 'required' => 'required']),
$html->tagHasChildren('label', ['for' => 'tilde'], 'Your tilde/pubnix (required)'),
$html->tag('input', ['id' => 'tilde', 'name' => 'tilde', 'type' => 'text', 'required' => 'required']),
$html->tagHasChildren('label', ['for' => 'message'], 'Anything you want to mention?'),
$html->tagHasChildren('textarea', ['id' => 'message', 'name' => 'message'], ''),
$html->tagHasChildren('label', ['for' => 'verify'], "What is {$numbers[0]} plus {$numbers[1]}?"),
$html->tag('input', ['id' => 'verify', 'name' => 'verify', 'type' => 'number', 'required' => 'required']),
$html->tagHasChildren('button', ['type' => 'submit'], 'Submit request'),
]),
]),
],
));
return $response;
}
/**
* @param Request $request The Request object
* @param Response $response The Response object
* @param mixed[] $args Arguments passed from the router (if any)
* @return Response The resulting Response object
*/
public function requestPOST(Request $request, Response $response, ?array $args = []): Response {
$session = $this->container->get('session')->ensure_create()->retrieve();
if (!array_key_exists('numbers', $session->session_data)) {
return $response->withHeader('Location', '/register');
}
// Get the numbers from the session, and then reset them
$numbers = array_map((function($i) { return intval($i); }), explode(',', $session->session_data['numbers']));
unset($session->session_data['numbers']);
$form_values = (array) $request->getParsedBody();
// Check CSRF
$csrf_token = null;
if (array_key_exists('_csrf', $form_values)) $csrf_token = trim($form_values['_csrf']);
$this->container->get('csrf')->check('csrf', $csrf_token);
// Check the math question
$given_sum = null;
if (array_key_exists('verify', $form_values)) $given_sum = intval(trim($form_values['verify']));
if ($given_sum != $numbers[0] + $numbers[1]) {
return $this->requestGET($request, $response, array_merge($args, [
'message' => 'The provided verification was incorrect.',
]));
}
// We're good, send the notifications
HookMachine::execute([self::class, 'sendAlert'], [
$form_values['username'],
$form_values['tilde'],
$form_values['message'] ?? '[no message provided]',
]);
// Destroy the session
$session->destroy();
// And return a success message
$html = $this->container->get('html');
$response->getBody()->write($html->renderDocument(
[
$html->tag('meta', ['charset' => 'utf-8']),
$html->tag('meta', ['name' => 'viewport', 'content' => 'initial-scale=1, width=device-width']),
$html->tag('link', ['rel' => 'stylesheet', 'href' => 'styles.css']),
$html->tagHasChildren('title', [], 'register for tel.tilde.org.nz'),
],
[
$html->tagHasChildren('main', [], ...[
$html->tagHasChildren('h1', [], ...[
'register for ',
$html->tagHasChildren('a', ['href' => 'https://tel.tilde.org.nz'], 'tel.tilde.org.nz'),
]),
$html->tagHasChildren('div', ['class' => 'message'], ...[
"Your registration request has been submitted!",
]),
]),
],
));
return $response;
}
}