Skip to content

Feature/add security header #319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 0 additions & 33 deletions app/Http/Controllers/User/DashboardController.php

This file was deleted.

48 changes: 48 additions & 0 deletions app/Http/Middleware/CacheHeaders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

final class CacheHeaders
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var \Illuminate\Http\Response $response
*/
$response = $next($request);

if (Auth::check()) {
$response->setCache(
options: [
'private' => true,
'max_age' => 0,
's_maxage' => 0,
'no_store' => true,
],
);
} else {
$response->setCache(
options: [
'public' => true,
'max_age' => 60,
's_maxage' => 60,
],
);

foreach ($response->headers->getCookies() as $cookie) {
$response->headers->removeCookie(
name: $cookie->getName(),
);
}
}

return $response;
}
}
26 changes: 26 additions & 0 deletions app/Http/Middleware/Security/ContentSecurityPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware\Security;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class ContentSecurityPolicy
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var Response $response
*/
$response = $next($request);

$response->headers->add([
'Content-Security-Policy' => "default-src 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; img-src *;",
]);

return $response;
}
}
26 changes: 26 additions & 0 deletions app/Http/Middleware/Security/PermissionsPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware\Security;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class PermissionsPolicy
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var Response $response
*/
$response = $next($request);

$response->headers->add([
'Permissions-Policy' => 'geolocation=(self), microphone=()',
]);

return $response;
}
}
26 changes: 26 additions & 0 deletions app/Http/Middleware/Security/ReferrerPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware\Security;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class ReferrerPolicy
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var Response $response
*/
$response = $next($request);

$response->headers->add([
'Referrer-Policy' => 'no-referrer',
]);

return $response;
}
}
26 changes: 26 additions & 0 deletions app/Http/Middleware/Security/StrictTransportSecurity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware\Security;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class StrictTransportSecurity
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var Response $response
*/
$response = $next($request);

$response->headers->add([
'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains; preload',
]);

return $response;
}
}
26 changes: 26 additions & 0 deletions app/Http/Middleware/Security/XFrameOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware\Security;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class XFrameOption
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var Response $response
*/
$response = $next($request);

$response->headers->add([
'X-Frame-Options' => 'deny',
]);

return $response;
}
}
28 changes: 0 additions & 28 deletions app/Http/Middleware/TrackLastActivity.php

This file was deleted.

2 changes: 1 addition & 1 deletion app/Livewire/Components/Discussion/Comments.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function comments(): Collection
$replies = collect();

// @phpstan-ignore-next-line
foreach ($this->discussion->replies->load(['allChildReplies', 'user']) as $reply) {
foreach ($this->discussion->replies->load(['allChildReplies', 'user', 'user.media']) as $reply) {
/** @var Reply $reply */
if ($reply->allChildReplies->isNotEmpty()) {
foreach ($reply->allChildReplies as $childReply) {
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/Components/User/Articles.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class Articles extends Component implements HasActions, HasForms
#[Computed]
public function articles(): LengthAwarePaginator
{
return Article::with(['user', 'tags', 'reactions'])
return Article::with('tags', 'reactions')
->where('user_id', Auth::id())
->latest()
->paginate(10);
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/Components/User/Discussions.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class Discussions extends Component implements HasActions, HasForms
#[Computed]
public function discussions(): LengthAwarePaginator
{
return Discussion::with('user')
return Discussion::with('tags', 'replies')
->where('user_id', Auth::id())
->latest()
->paginate(10);
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/Components/User/Threads.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class Threads extends Component implements HasActions, HasForms
#[Computed]
public function threads(): LengthAwarePaginator
{
return Thread::with('user')
return Thread::with('channels', 'solutionReply', 'replies')
->scopes('withViewsCount')
->where('user_id', Auth::id())
->latest()
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/Pages/Account/Dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class Dashboard extends Component
#[Computed]
public function user(): User
{
return User::query()
return User::with('providers')
->scopes('withCounts')
->find(Auth::id());
}
Expand Down
13 changes: 9 additions & 4 deletions app/Livewire/Pages/Articles/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Models\Tag;
use App\Traits\WithLocale;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Cache;
use Livewire\Component;
use Livewire\WithoutUrlPagination;
use Livewire\WithPagination;
Expand All @@ -26,7 +27,7 @@ public function mount(): void
public function render(): View
{
return view('livewire.pages.articles.index', [
'articles' => Article::with(['tags', 'user', 'user.transactions']) // @phpstan-ignore-line
'articles' => Article::with(['tags', 'user', 'user.transactions', 'user.media', 'media']) // @phpstan-ignore-line
->withCount(['views', 'reactions'])
->orderByDesc('sponsored_at')
->orderByDesc('published_at')
Expand All @@ -35,9 +36,13 @@ public function render(): View
->forLocale($this->locale)
->simplePaginate(21),

'tags' => Tag::query()->whereHas('articles', function ($query): void {
$query->published();
})->orderBy('name')->get(),
'tags' => Cache::remember(
key: 'articles.tags',
ttl: now()->addWeek(),
callback: fn () => Tag::query()->whereHas('articles', function ($query): void {
$query->published();
})->orderBy('name')->get()
),
])
->title(__('pages/article.title'));
}
Expand Down
15 changes: 10 additions & 5 deletions app/Livewire/Pages/Discussions/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Models\Tag;
use App\Traits\WithLocale;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Cache;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithoutUrlPagination;
Expand Down Expand Up @@ -57,15 +58,19 @@ public function tagExists(string $tag): bool
public function render(): View
{
/** @var DiscussionQueryBuilder $query */
$query = Discussion::with(['tags', 'replies', 'user']) // @phpstan-ignore-line
$query = Discussion::with(['tags', 'replies', 'user', 'user.media', 'reactions']) // @phpstan-ignore-line
->withCount('replies')
->forLocale($this->locale)
->notPinned();

$tags = Tag::query()
->whereJsonContains('concerns', ['discussion'])
->orderBy('name')
->get();
$tags = Cache::remember(
key: 'discussions.tags',
ttl: now()->addWeek(),
callback: fn () => Tag::query()
->whereJsonContains('concerns', ['discussion'])
->orderBy('name')
->get()
);

if ($this->currentTag) {
$query->forTag($this->currentTag); // @phpstan-ignore-line
Expand Down
2 changes: 1 addition & 1 deletion app/Livewire/Pages/Discussions/SingleDiscussion.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function mount(): void
->twitterDescription($this->discussion->excerpt(100))
->withUrl();

$this->discussion->load('tags', 'replies', 'reactions', 'replies.user', 'user');
$this->discussion->load('tags', 'replies', 'reactions', 'user', 'user.media');
}

public function editAction(): Action
Expand Down
7 changes: 4 additions & 3 deletions app/Livewire/Pages/Forum/DetailThread.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ final class DetailThread extends Component implements HasActions, HasForms

public Thread $thread;

public function mount(Thread $thread): void
public function mount(): void
{
views($thread)->cooldown(now()->addHour())->record();
views($this->thread)->cooldown(now()->addHour())->record();

$this->thread = $thread->loadCount('views');
$this->thread->load('channels', 'channels.parent', 'user', 'user.media', 'replies', 'solutionReply')
->loadCount('views');
}

public function editAction(): Action
Expand Down
3 changes: 2 additions & 1 deletion app/Livewire/Pages/Forum/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ protected function applySorting(Builder $query): Builder

public function render(): View
{
$query = Thread::with(['channels', 'user']);
$query = Thread::with(['channels', 'user', 'user.media'])
->withCount('replies');

$query = $this->applyChannel($query);
$query = $this->applySearch($query);
Expand Down
Loading
Loading