feat: add guestbook with rate limiting (#6)
* Re-add guestbook w/ rate limiting * Add guestbook to navbar
This commit is contained in:
parent
1b267f6102
commit
8482a98ca6
12 changed files with 329 additions and 91 deletions
29
app/Http/Controllers/GuestbookController.php
Normal file
29
app/Http/Controllers/GuestbookController.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use DB;
|
||||||
|
|
||||||
|
class GuestbookController extends Controller {
|
||||||
|
public function guestbook() {
|
||||||
|
return view('pages.guestbook');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function guestbookPost(Request $request) {
|
||||||
|
$this->validate($request, [
|
||||||
|
'name' => 'required',
|
||||||
|
'message' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::insert('INSERT INTO guestbook_entries (name, timestamp, ip_address, agent, message) values (?, ?, ?, ?, ?)', array(
|
||||||
|
htmlspecialchars($request->get('name')),
|
||||||
|
time(),
|
||||||
|
$request->ip(),
|
||||||
|
$request->userAgent(),
|
||||||
|
htmlspecialchars($request->get('message'))
|
||||||
|
));
|
||||||
|
|
||||||
|
return back()->with('success', 'Entry submitted successfully!');
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,6 +45,11 @@ class Kernel extends HttpKernel
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $routeMiddleware = [
|
||||||
|
'rate_limit' => \App\Http\Middleware\RateLimiter::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The application's middleware aliases.
|
* The application's middleware aliases.
|
||||||
*
|
*
|
||||||
|
|
32
app/Http/Middleware/RateLimiter.php
Normal file
32
app/Http/Middleware/RateLimiter.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class RateLimiter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
$ipAddress = $request->ip();
|
||||||
|
$cacheKey = 'rate_limit_' . $ipAddress;
|
||||||
|
|
||||||
|
if (Cache::has($cacheKey)) {
|
||||||
|
// If the cache key exists, the IP has submitted an entry within the last hour
|
||||||
|
return response()->view('errors.ratelimit-guestbook', [], 429);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the IP address to the cache and set the expiration time to one hour
|
||||||
|
Cache::put($cacheKey, true, 60);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,8 @@
|
||||||
"guzzlehttp/guzzle": "^7.2",
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
"laravel/framework": "^10.10",
|
"laravel/framework": "^10.10",
|
||||||
"laravel/sanctum": "^3.2",
|
"laravel/sanctum": "^3.2",
|
||||||
"laravel/tinker": "^2.8"
|
"laravel/tinker": "^2.8",
|
||||||
|
"spatie/laravel-honeypot": "^4.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
|
138
composer.lock
generated
138
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "aa322c53454393ed775cfe4807d54a50",
|
"content-hash": "505f8d503188864625fc855900ea2202",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
|
@ -2994,6 +2994,142 @@
|
||||||
],
|
],
|
||||||
"time": "2023-04-15T23:01:58+00:00"
|
"time": "2023-04-15T23:01:58+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-honeypot",
|
||||||
|
"version": "4.3.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-honeypot.git",
|
||||||
|
"reference": "eab92dd2096f1cdb83c28ced4f4632d3cfde2872"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-honeypot/zipball/eab92dd2096f1cdb83c28ced4f4632d3cfde2872",
|
||||||
|
"reference": "eab92dd2096f1cdb83c28ced4f4632d3cfde2872",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^8.0|^9.0|^10.0",
|
||||||
|
"illuminate/encryption": "^8.0|^9.0|^10.0",
|
||||||
|
"illuminate/http": "^8.0|^9.0|^10.0",
|
||||||
|
"illuminate/support": "^8.0|^9.0|^10.0",
|
||||||
|
"illuminate/validation": "^8.0|^9.0|^10.0",
|
||||||
|
"nesbot/carbon": "^2.0",
|
||||||
|
"php": "^8.0",
|
||||||
|
"spatie/laravel-package-tools": "^1.9",
|
||||||
|
"symfony/http-foundation": "^5.1.2|^6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"livewire/livewire": "^2.10",
|
||||||
|
"orchestra/testbench": "^6.23|^7.0|^8.0",
|
||||||
|
"pestphp/pest-plugin-livewire": "^1.0",
|
||||||
|
"phpunit/phpunit": "^9.4",
|
||||||
|
"spatie/pest-plugin-snapshots": "^1.1",
|
||||||
|
"spatie/phpunit-snapshot-assertions": "^4.2",
|
||||||
|
"spatie/test-time": "^1.2.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Spatie\\Honeypot\\HoneypotServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\Honeypot\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Preventing spam submitted through forms",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-honeypot",
|
||||||
|
"keywords": [
|
||||||
|
"laravel-honeypot",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/spatie/laravel-honeypot/tree/4.3.2"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-01-17T07:09:34+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-package-tools",
|
||||||
|
"version": "1.15.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-package-tools.git",
|
||||||
|
"reference": "efab1844b8826443135201c4443690f032c3d533"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/efab1844b8826443135201c4443690f032c3d533",
|
||||||
|
"reference": "efab1844b8826443135201c4443690f032c3d533",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^9.28|^10.0",
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.5",
|
||||||
|
"orchestra/testbench": "^7.7|^8.0",
|
||||||
|
"pestphp/pest": "^1.22",
|
||||||
|
"phpunit/phpunit": "^9.5.24",
|
||||||
|
"spatie/pest-plugin-test-time": "^1.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\LaravelPackageTools\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Tools for creating Laravel packages",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-package-tools",
|
||||||
|
"keywords": [
|
||||||
|
"laravel-package-tools",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/laravel-package-tools/issues",
|
||||||
|
"source": "https://github.com/spatie/laravel-package-tools/tree/1.15.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-04-27T08:09:01+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v6.3.0",
|
"version": "v6.3.0",
|
||||||
|
|
|
@ -34,15 +34,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'connections' => [
|
'connections' => [
|
||||||
|
|
||||||
'sqlite' => [
|
|
||||||
'driver' => 'sqlite',
|
|
||||||
'url' => env('DATABASE_URL'),
|
|
||||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
|
||||||
'prefix' => '',
|
|
||||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
|
||||||
],
|
|
||||||
|
|
||||||
'mysql' => [
|
'mysql' => [
|
||||||
'driver' => 'mysql',
|
'driver' => 'mysql',
|
||||||
'url' => env('DATABASE_URL'),
|
'url' => env('DATABASE_URL'),
|
||||||
|
@ -62,37 +53,6 @@
|
||||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||||
]) : [],
|
]) : [],
|
||||||
],
|
],
|
||||||
|
|
||||||
'pgsql' => [
|
|
||||||
'driver' => 'pgsql',
|
|
||||||
'url' => env('DATABASE_URL'),
|
|
||||||
'host' => env('DB_HOST', '127.0.0.1'),
|
|
||||||
'port' => env('DB_PORT', '5432'),
|
|
||||||
'database' => env('DB_DATABASE', 'forge'),
|
|
||||||
'username' => env('DB_USERNAME', 'forge'),
|
|
||||||
'password' => env('DB_PASSWORD', ''),
|
|
||||||
'charset' => 'utf8',
|
|
||||||
'prefix' => '',
|
|
||||||
'prefix_indexes' => true,
|
|
||||||
'search_path' => 'public',
|
|
||||||
'sslmode' => 'prefer',
|
|
||||||
],
|
|
||||||
|
|
||||||
'sqlsrv' => [
|
|
||||||
'driver' => 'sqlsrv',
|
|
||||||
'url' => env('DATABASE_URL'),
|
|
||||||
'host' => env('DB_HOST', 'localhost'),
|
|
||||||
'port' => env('DB_PORT', '1433'),
|
|
||||||
'database' => env('DB_DATABASE', 'forge'),
|
|
||||||
'username' => env('DB_USERNAME', 'forge'),
|
|
||||||
'password' => env('DB_PASSWORD', ''),
|
|
||||||
'charset' => 'utf8',
|
|
||||||
'prefix' => '',
|
|
||||||
'prefix_indexes' => true,
|
|
||||||
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
|
|
||||||
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
|
|
||||||
],
|
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -107,45 +67,4 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'migrations' => 'migrations',
|
'migrations' => 'migrations',
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Redis Databases
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Redis is an open source, fast, and advanced key-value store that also
|
|
||||||
| provides a richer body of commands than a typical key-value system
|
|
||||||
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'redis' => [
|
|
||||||
|
|
||||||
'client' => env('REDIS_CLIENT', 'phpredis'),
|
|
||||||
|
|
||||||
'options' => [
|
|
||||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
|
||||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
|
||||||
],
|
|
||||||
|
|
||||||
'default' => [
|
|
||||||
'url' => env('REDIS_URL'),
|
|
||||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
|
||||||
'username' => env('REDIS_USERNAME'),
|
|
||||||
'password' => env('REDIS_PASSWORD'),
|
|
||||||
'port' => env('REDIS_PORT', '6379'),
|
|
||||||
'database' => env('REDIS_DB', '0'),
|
|
||||||
],
|
|
||||||
|
|
||||||
'cache' => [
|
|
||||||
'url' => env('REDIS_URL'),
|
|
||||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
|
||||||
'username' => env('REDIS_USERNAME'),
|
|
||||||
'password' => env('REDIS_PASSWORD'),
|
|
||||||
'port' => env('REDIS_PORT', '6379'),
|
|
||||||
'database' => env('REDIS_CACHE_DB', '1'),
|
|
||||||
],
|
|
||||||
|
|
||||||
],
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -115,6 +115,10 @@ div.preview pre.small, div.project pre.small {
|
||||||
div.preview pre, div.project pre {
|
div.preview pre, div.project pre {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0.2em;
|
||||||
|
max-width: 90%
|
||||||
}
|
}
|
||||||
|
|
||||||
div.project pre {
|
div.project pre {
|
||||||
|
@ -283,13 +287,6 @@ .header {
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.preview pre, div.project pre {
|
|
||||||
display: inline-block;
|
|
||||||
text-align: left;
|
|
||||||
padding: 0.2em;
|
|
||||||
max-width: 90%
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 { font-size: 150% }
|
h1 { font-size: 150% }
|
||||||
h2 { font-size: 130% }
|
h2 { font-size: 130% }
|
||||||
h3 { font-size: 115% }
|
h3 { font-size: 115% }
|
||||||
|
@ -324,3 +321,32 @@ a {
|
||||||
color: #99f;
|
color: #99f;
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.gb_entryform tr td {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_entryform tr td label {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_entryform tr td span.text-danger {
|
||||||
|
padding-left: 5px;
|
||||||
|
color: rgb(255, 114, 114);
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_entryform tr td textarea,
|
||||||
|
table.gb_entryform tr td input {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_entry tr td {
|
||||||
|
border: solid #FFFFFF;
|
||||||
|
width: 500px;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_entry {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
11
public/css/minimal.css
Normal file
11
public/css/minimal.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
html {
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
margin: 0px;
|
||||||
|
margin-left: 10px;
|
||||||
|
color: #ddd;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
16
resources/views/errors/ratelimit-guestbook.blade.php
Normal file
16
resources/views/errors/ratelimit-guestbook.blade.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Error 429: Overclocking Detected!</title>
|
||||||
|
<link rel="stylesheet" href="{{ URL::asset ('css/minimal.css') }}"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Error 429: Overclocking Detected!</h1>
|
||||||
|
<hr/>
|
||||||
|
<p>Whoa there! Your submissions are going at warp speed.</p>
|
||||||
|
<p>Remember you can only submit an entry <u>once every hour</u>!</p>
|
||||||
|
<br/>
|
||||||
|
Click <a href="/guestbook">here</a> to go back to the guestbook.
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -6,6 +6,7 @@
|
||||||
<a href="/projects/">projects</a> |
|
<a href="/projects/">projects</a> |
|
||||||
<a href="/calculators/">calculators</a> |
|
<a href="/calculators/">calculators</a> |
|
||||||
<a href="/computers/">computers</a> |
|
<a href="/computers/">computers</a> |
|
||||||
<a href="/bookmarks/">bookmarks</a>
|
<a href="/bookmarks/">bookmarks</a> |
|
||||||
|
<a href="/guestbook/">guestbook</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
53
resources/views/pages/guestbook.blade.php
Normal file
53
resources/views/pages/guestbook.blade.php
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
@extends('layouts.default')
|
||||||
|
@section('title', 'guestbook')
|
||||||
|
@section('content')
|
||||||
|
<br/>
|
||||||
|
<form method="POST" action="/guestbook">
|
||||||
|
@csrf
|
||||||
|
<x-honeypot />
|
||||||
|
<table class="gb_entryform">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="name">Name:</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input name="name" type="text" id="name" placeholder="John Doe">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="text-danger">{{ $errors->first('name') }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="message">Message:</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea name="message" id="message" rows="3"></textarea>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="text-danger">{{ $errors->first('message') }}</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
<p>You can submit an entry <u>once every hour</u>.</p>
|
||||||
|
<p>Your IP address <u>will</u> be logged but <u>will not</u> be publically displayed.</p>
|
||||||
|
<hr/>
|
||||||
|
@php
|
||||||
|
$entries = DB::select('SELECT name, timestamp, message FROM guestbook_entries ORDER BY id DESC');
|
||||||
|
@endphp
|
||||||
|
<h1>Entries <small>({{ count($entries) }} total)</small></h1>
|
||||||
|
@foreach ($entries as $entry)
|
||||||
|
<table class="gb_entry"><tr><td>
|
||||||
|
Name: {{ $entry->name }}<br/>
|
||||||
|
Date: {{ gmdate("H:i:s - Y-m-d", $entry->timestamp) }}<br/><br/>
|
||||||
|
{{ htmlspecialchars($entry->message) }}
|
||||||
|
</td></tr></table>
|
||||||
|
@endforeach
|
||||||
|
@stop
|
||||||
|
|
|
@ -32,3 +32,12 @@
|
||||||
Route::get('/computers', function () {
|
Route::get('/computers', function () {
|
||||||
return View::make('pages.computers');
|
return View::make('pages.computers');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::get('/guestbook', 'App\Http\Controllers\GuestbookController@guestbook')
|
||||||
|
->name('guestbook');
|
||||||
|
|
||||||
|
Route::post('/guestbook', 'App\Http\Controllers\GuestbookController@guestbookpost')
|
||||||
|
->name('guestbookPost')
|
||||||
|
->middleware('rate_limit');
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue