feat: site admin (#8)
This commit is contained in:
parent
691d0d933d
commit
7c16dc53b5
15 changed files with 1378 additions and 52 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,3 +17,4 @@ yarn-error.log
|
||||||
/.fleet
|
/.fleet
|
||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
|
.auth0.*.json
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.1",
|
"php": "^8.1",
|
||||||
|
"auth0/login": "^7.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",
|
||||||
|
|
1171
composer.lock
generated
1171
composer.lock
generated
File diff suppressed because it is too large
Load diff
56
config/auth0.php
Normal file
56
config/auth0.php
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Auth0\Laravel\Configuration;
|
||||||
|
use Auth0\SDK\Configuration\SdkConfiguration;
|
||||||
|
|
||||||
|
return Configuration::VERSION_2 + [
|
||||||
|
'registerGuards' => true,
|
||||||
|
'registerMiddleware' => true,
|
||||||
|
'registerAuthenticationRoutes' => true,
|
||||||
|
'configurationPath' => null,
|
||||||
|
|
||||||
|
'guards' => [
|
||||||
|
'default' => [
|
||||||
|
Configuration::CONFIG_STRATEGY => Configuration::get(Configuration::CONFIG_STRATEGY, SdkConfiguration::STRATEGY_NONE),
|
||||||
|
Configuration::CONFIG_DOMAIN => Configuration::get(Configuration::CONFIG_DOMAIN),
|
||||||
|
Configuration::CONFIG_CUSTOM_DOMAIN => Configuration::get(Configuration::CONFIG_CUSTOM_DOMAIN),
|
||||||
|
Configuration::CONFIG_CLIENT_ID => Configuration::get(Configuration::CONFIG_CLIENT_ID),
|
||||||
|
Configuration::CONFIG_CLIENT_SECRET => Configuration::get(Configuration::CONFIG_CLIENT_SECRET),
|
||||||
|
Configuration::CONFIG_AUDIENCE => Configuration::get(Configuration::CONFIG_AUDIENCE),
|
||||||
|
Configuration::CONFIG_ORGANIZATION => Configuration::get(Configuration::CONFIG_ORGANIZATION),
|
||||||
|
Configuration::CONFIG_USE_PKCE => Configuration::get(Configuration::CONFIG_USE_PKCE),
|
||||||
|
Configuration::CONFIG_SCOPE => Configuration::get(Configuration::CONFIG_SCOPE),
|
||||||
|
Configuration::CONFIG_RESPONSE_MODE => Configuration::get(Configuration::CONFIG_RESPONSE_MODE),
|
||||||
|
Configuration::CONFIG_RESPONSE_TYPE => Configuration::get(Configuration::CONFIG_RESPONSE_TYPE),
|
||||||
|
Configuration::CONFIG_TOKEN_ALGORITHM => Configuration::get(Configuration::CONFIG_TOKEN_ALGORITHM),
|
||||||
|
Configuration::CONFIG_TOKEN_JWKS_URI => Configuration::get(Configuration::CONFIG_TOKEN_JWKS_URI),
|
||||||
|
Configuration::CONFIG_TOKEN_MAX_AGE => Configuration::get(Configuration::CONFIG_TOKEN_MAX_AGE),
|
||||||
|
Configuration::CONFIG_TOKEN_LEEWAY => Configuration::get(Configuration::CONFIG_TOKEN_LEEWAY),
|
||||||
|
Configuration::CONFIG_TOKEN_CACHE => Configuration::get(Configuration::CONFIG_TOKEN_CACHE),
|
||||||
|
Configuration::CONFIG_TOKEN_CACHE_TTL => Configuration::get(Configuration::CONFIG_TOKEN_CACHE_TTL),
|
||||||
|
Configuration::CONFIG_HTTP_MAX_RETRIES => Configuration::get(Configuration::CONFIG_HTTP_MAX_RETRIES),
|
||||||
|
Configuration::CONFIG_HTTP_TELEMETRY => Configuration::get(Configuration::CONFIG_HTTP_TELEMETRY),
|
||||||
|
Configuration::CONFIG_MANAGEMENT_TOKEN => Configuration::get(Configuration::CONFIG_MANAGEMENT_TOKEN),
|
||||||
|
Configuration::CONFIG_MANAGEMENT_TOKEN_CACHE => Configuration::get(Configuration::CONFIG_MANAGEMENT_TOKEN_CACHE),
|
||||||
|
Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_KEY => Configuration::get(Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_KEY),
|
||||||
|
Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_ALGORITHM => Configuration::get(Configuration::CONFIG_CLIENT_ASSERTION_SIGNING_ALGORITHM),
|
||||||
|
Configuration::CONFIG_PUSHED_AUTHORIZATION_REQUEST => Configuration::get(Configuration::CONFIG_PUSHED_AUTHORIZATION_REQUEST),
|
||||||
|
],
|
||||||
|
|
||||||
|
'api' => [
|
||||||
|
Configuration::CONFIG_STRATEGY => SdkConfiguration::STRATEGY_API,
|
||||||
|
],
|
||||||
|
|
||||||
|
'web' => [
|
||||||
|
Configuration::CONFIG_STRATEGY => SdkConfiguration::STRATEGY_REGULAR,
|
||||||
|
Configuration::CONFIG_COOKIE_SECRET => Configuration::get(Configuration::CONFIG_COOKIE_SECRET, env('APP_KEY')),
|
||||||
|
Configuration::CONFIG_REDIRECT_URI => Configuration::get(Configuration::CONFIG_REDIRECT_URI, env('APP_URL') . '/callback'),
|
||||||
|
Configuration::CONFIG_SESSION_STORAGE => Configuration::get(Configuration::CONFIG_SESSION_STORAGE),
|
||||||
|
Configuration::CONFIG_SESSION_STORAGE_ID => Configuration::get(Configuration::CONFIG_SESSION_STORAGE_ID),
|
||||||
|
Configuration::CONFIG_TRANSIENT_STORAGE => Configuration::get(Configuration::CONFIG_TRANSIENT_STORAGE),
|
||||||
|
Configuration::CONFIG_TRANSIENT_STORAGE_ID => Configuration::get(Configuration::CONFIG_TRANSIENT_STORAGE_ID),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
|
@ -350,3 +350,29 @@ table.gb_entry tr td {
|
||||||
table.gb_entry {
|
table.gb_entry {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.gb_admin {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
width: 500px;
|
||||||
|
border: #FFFFFF solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_admin tr td {
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: none;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_admin tr td.gb_del {
|
||||||
|
border-left: none;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.gb_admin tr td.gb_message {
|
||||||
|
border-top: none;
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
|
@ -9,3 +9,7 @@ body {
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.gb_entry_details tr td {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
9
resources/views/errors/generic-error.blade.php
Normal file
9
resources/views/errors/generic-error.blade.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
@extends('layouts.minimal')
|
||||||
|
@section('title', 'Error 401: Unauthorized User!')
|
||||||
|
@section('content')
|
||||||
|
<h1>{{ $error }}</h1>
|
||||||
|
<hr/>
|
||||||
|
@if(isset($description))
|
||||||
|
<p>{{ $description }}</p>
|
||||||
|
@endif
|
||||||
|
@stop
|
8
resources/views/errors/no-auth.blade.php
Normal file
8
resources/views/errors/no-auth.blade.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
@extends('layouts.minimal')
|
||||||
|
@section('title', 'Error 401: Unauthorized User!')
|
||||||
|
@section('content')
|
||||||
|
<h1>Error 401: Unauthorized User!</h1>
|
||||||
|
<hr/>
|
||||||
|
<p>Woah there! Only authorized users can access this page. Please <a href="/login">log in</a> to proceed.</p>
|
||||||
|
<p>Ended up here on accident? Click <a href="/">here</a> to return to the homepage</u>!</p>
|
||||||
|
@stop
|
12
resources/views/includes/admin/header.blade.php
Normal file
12
resources/views/includes/admin/header.blade.php
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<nav>
|
||||||
|
<div>
|
||||||
|
<a href="/">public home</a> |
|
||||||
|
<a href="/admin">admin home</a> |
|
||||||
|
<a href="/admin/guestbook">guestbook</a>
|
||||||
|
@if (auth()->check())
|
||||||
|
| ({{ auth()->user()->name }}) <a href="/logout">logout</a>
|
||||||
|
@else
|
||||||
|
| <a href="/login">login</a>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</nav>
|
|
@ -8,5 +8,11 @@
|
||||||
<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>
|
<a href="/guestbook/">guestbook</a>
|
||||||
|
@if (auth()->check())
|
||||||
|
| <a href="/admin/">admin</a>
|
||||||
|
| ({{ auth()->user()->name }}) <a href="/logout">logout</a>
|
||||||
|
@else
|
||||||
|
| <a href="/login">login</a>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
23
resources/views/layouts/default-admin.blade.php
Normal file
23
resources/views/layouts/default-admin.blade.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
@include('includes.head')
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<div class="header">
|
||||||
|
@include('includes.admin.header')
|
||||||
|
</div> <!-- header -->
|
||||||
|
|
||||||
|
<div id="pagebody">
|
||||||
|
<div id="content">
|
||||||
|
@yield('content')
|
||||||
|
</div> <!-- content -->
|
||||||
|
<div id="footer" class="pagefooter">
|
||||||
|
@include('includes.footer')
|
||||||
|
</div> <!-- footer -->
|
||||||
|
</div> <!-- pagebody -->
|
||||||
|
</div> <!-- page -->
|
||||||
|
</body>
|
||||||
|
</html>
|
33
resources/views/pages/admin/guestbook-del-confirm.blade.php
Normal file
33
resources/views/pages/admin/guestbook-del-confirm.blade.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@extends('layouts.minimal')
|
||||||
|
@section('title', 'Delete confirm')
|
||||||
|
@section('content')
|
||||||
|
<h1>Delete Confirmation</h1>
|
||||||
|
<hr/>
|
||||||
|
<p>Are you sure you want to delete this entry?</p>
|
||||||
|
|
||||||
|
<h3>Entry Details:</h3>
|
||||||
|
<table class="gb_entry_details">
|
||||||
|
<tr>
|
||||||
|
<td><b>ID:</b></td>
|
||||||
|
<td>{{ $entry->id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Name:</b></td>
|
||||||
|
<td>{{ $entry->name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Date:</b></td>
|
||||||
|
<td>{{ gmdate("H:i:s - Y-m-d", $entry->timestamp) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Message:</b></td>
|
||||||
|
<td>{{ $entry->message }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<form action="/admin/guestbook/delete" method="POST">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="id" value="{{ $entry->id }}">
|
||||||
|
<button type="submit">Confirm Delete</button>
|
||||||
|
</form>
|
||||||
|
@stop
|
27
resources/views/pages/admin/guestbook.blade.php
Normal file
27
resources/views/pages/admin/guestbook.blade.php
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
@extends('layouts.default-admin')
|
||||||
|
@section('title', 'guestbook')
|
||||||
|
@section('content')
|
||||||
|
@php
|
||||||
|
$entries = DB::select('SELECT id, 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_admin">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Name: {{ $entry->name }}<br/>
|
||||||
|
Date: {{ gmdate("H:i:s - Y-m-d", $entry->timestamp) }}
|
||||||
|
</td>
|
||||||
|
<td class="gb_del">
|
||||||
|
<a href="/admin/guestbook/delete?id={{ $entry->id }}">del</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" class="gb_message">
|
||||||
|
<br/>
|
||||||
|
{{ htmlspecialchars($entry->message) }}
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
@endforeach
|
||||||
|
@stop
|
||||||
|
|
9
resources/views/pages/admin/index.blade.php
Normal file
9
resources/views/pages/admin/index.blade.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
@extends('layouts.default-admin')
|
||||||
|
@section('title', 'Page Title')
|
||||||
|
@section('description', 'Page description goes here')
|
||||||
|
@php
|
||||||
|
$user = auth()->user();
|
||||||
|
@endphp
|
||||||
|
@section('content')
|
||||||
|
<p>You are logged in as {{ $user->name }} ({{ $user->email }})</p>
|
||||||
|
@stop
|
|
@ -40,4 +40,46 @@
|
||||||
->name('guestbookPost')
|
->name('guestbookPost')
|
||||||
->middleware('rate_limit');
|
->middleware('rate_limit');
|
||||||
|
|
||||||
|
Route::get('/admin', function () {
|
||||||
|
if (!auth()->check()) {
|
||||||
|
return view('errors.no-auth');
|
||||||
|
}
|
||||||
|
return view('pages.admin.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::get('/admin/guestbook', function () {
|
||||||
|
if (!auth()->check()) {
|
||||||
|
return view('errors.no-auth');
|
||||||
|
}
|
||||||
|
return view('pages.admin.guestbook');
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::get('/admin/guestbook/delete', function () {
|
||||||
|
if (!auth()->check()) {
|
||||||
|
return view('errors.no-auth');
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = request()->input('id');
|
||||||
|
$entry = DB::table('guestbook_entries')->find($id);
|
||||||
|
|
||||||
|
if ($entry) {
|
||||||
|
// Render a confirmation view
|
||||||
|
return View::make('pages.admin.guestbook-del-confirm', compact('entry'));
|
||||||
|
} else {
|
||||||
|
return view('errors.generic-error')
|
||||||
|
->with('error', "Entry not found")
|
||||||
|
->with('description', "The specified entry does not exist!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::post('/admin/guestbook/delete', function () {
|
||||||
|
if (!auth()->check()) {
|
||||||
|
return view('errors.no-auth');
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = request()->input('id');
|
||||||
|
DB::table('guestbook_entries')->where('id', $id)->delete();
|
||||||
|
|
||||||
|
return back()->with('success', 'Entry deleted successfully!');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue