diff --git a/CHANGELOG.md b/CHANGELOG.md index d7ee1304e669888538b4d066f987a62db61a453d..17f621e09d6cdde9c469079534bfaca30e0fea51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added - Added ```BANNED_USERNAMES``` .env var, an optional comma separated string to ban specific usernames from being used ([6cdd64c6](https://github.com/pixelfed/pixelfed/commit/6cdd64c6)) - Added RestrictedAccess middleware for Restricted Mode ([17c1a83d](https://github.com/pixelfed/pixelfed/commit/17c1a83d)) +- Added FailedJob garbage collection ([5d424f12](https://github.com/pixelfed/pixelfed/commit/5d424f12)) +- Added Password Reset garbage collection ([829c41e1](https://github.com/pixelfed/pixelfed/commit/829c41e1)) ### Fixed - Fixed Story Compose bug affecting postgres instances ([#1918](https://github.com/pixelfed/pixelfed/pull/1918)) @@ -22,6 +24,9 @@ - Updated StoryCompose component, added upload progress page ([2de3c56f](https://github.com/pixelfed/pixelfed/commit/2de3c56f)) - Updated instance config, cleanup and add restricted mode ([3be32597](https://github.com/pixelfed/pixelfed/commit/3be32597)) - Update RelationshipSettings Controller, fixes #1605 ([4d2da2f1](https://github.com/pixelfed/pixelfed/commit/4d2da2f1)) +- Updated password reset, now expires after 24 hours ([829c41e1](https://github.com/pixelfed/pixelfed/commit/829c41e1)) +- Updated nav layout ([73249dc2](https://github.com/pixelfed/pixelfed/commit/73249dc2)) +- Updated views with noscript warnings ([eaca43a6](https://github.com/pixelfed/pixelfed/commit/eaca43a6)) ### Changed diff --git a/app/Console/Commands/FailedJobGC.php b/app/Console/Commands/FailedJobGC.php new file mode 100644 index 0000000000000000000000000000000000000000..f48d49b84e51cf362677b83c9286f3f32b66ca3b --- /dev/null +++ b/app/Console/Commands/FailedJobGC.php @@ -0,0 +1,49 @@ +<?php + +namespace App\Console\Commands; + +use Illuminate\Console\Command; +use App\FailedJob; + +class FailedJobGC extends Command +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'gc:failedjobs'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Delete failed jobs over 1 month old'; + + /** + * Create a new command instance. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + FailedJob::chunk(50, function($jobs) { + foreach($jobs as $job) { + if($job->failed_at->lt(now()->subMonth())) { + $job->delete(); + } + } + }); + } +} diff --git a/app/Console/Commands/PasswordResetGC.php b/app/Console/Commands/PasswordResetGC.php new file mode 100644 index 0000000000000000000000000000000000000000..2dbcc35e63be21f1cb887efb5cbe2aeee4886a14 --- /dev/null +++ b/app/Console/Commands/PasswordResetGC.php @@ -0,0 +1,48 @@ +<?php + +namespace App\Console\Commands; + +use Illuminate\Console\Command; +use App\EmailVerification; + +class PasswordResetGC extends Command +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'gc:passwordreset'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Delete password reset tokens over 24 hours old'; + + /** + * Create a new command instance. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + EmailVerification::where('created_at', '<', now()->subMinutes(1441)) + ->chunk(50, function($emails) { + foreach($emails as $em) { + $em->delete(); + } + }); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 1e3364afc7477c74dc0e86e02e3097024c1c2539..a29ace3551809a5ec16698ebe7726c94143c623b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -31,6 +31,8 @@ class Kernel extends ConsoleKernel ->hourly(); $schedule->command('horizon:snapshot')->everyFiveMinutes(); $schedule->command('story:gc')->everyFiveMinutes(); + $schedule->command('gc:failedjobs')->dailyAt(3); + $schedule->command('gc:passwordreset')->dailyAt('09:41'); } /** diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 57301a8b130cee77627ad183b9457adc1f6f713f..37ccbba3f04427773b4a61edef380e5d36e40d9c 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -6,6 +6,7 @@ use Auth; use Cache; use Mail; use Illuminate\Support\Facades\Redis; +use Illuminate\Support\Str; use Carbon\Carbon; use App\Mail\ConfirmEmail; use Illuminate\Http\Request; @@ -80,8 +81,8 @@ class AccountController extends Controller EmailVerification::whereUserId(Auth::id())->delete(); $user = User::whereNull('email_verified_at')->find(Auth::id()); - $utoken = str_random(64); - $rtoken = str_random(128); + $utoken = Str::uuid() . Str::random(mt_rand(5,9)); + $rtoken = Str::random(mt_rand(64, 70)); $verify = new EmailVerification(); $verify->user_id = $user->id; @@ -98,7 +99,7 @@ class AccountController extends Controller public function confirmVerifyEmail(Request $request, $userToken, $randomToken) { $verify = EmailVerification::where('user_token', $userToken) - ->where('created_at', '>', now()->subWeeks(2)) + ->where('created_at', '>', now()->subHours(24)) ->where('random_token', $randomToken) ->firstOrFail(); diff --git a/resources/views/emails/confirm_email.blade.php b/resources/views/emails/confirm_email.blade.php index cb521c9b97c1a63d6527f0a93f19c4861932792f..2fc98a75162e555c6a59ca5e027dac82906f02d6 100644 --- a/resources/views/emails/confirm_email.blade.php +++ b/resources/views/emails/confirm_email.blade.php @@ -1,12 +1,17 @@ @component('mail::message') # Email Confirmation -Please confirm your email address. +Hello <b>@{{$verify->user->username}}</b>, please confirm your email address. + +If you did not create this account, please disregard this email. @component('mail::button', ['url' => $verify->url()]) Confirm Email @endcomponent +<p>This link expires after 24 hours.</p> +<br> + Thanks,<br> -{{ config('pixelfed.domain.app') }} +<a href="{{ config('app.url') }}">{{ config('pixelfed.domain.app') }}</a> @endcomponent diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 46b01ba82d7a98898324ec0e425b11ab297a0c52..c46cc59b4bab54b7606236d05d8fc7c60a8c3c92 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -41,6 +41,12 @@ @include('layouts.partial.nav') <main id="content"> @yield('content') + <noscript> + <div class="container"> + <p class="pt-5 text-center lead">Please enable javascript to view this content.</p> + </div> + + </noscript> <div class="modal pr-0" tabindex="-1" role="dialog" id="composeModal"> <div class="modal-dialog" role="document"> <div class="modal-content"> diff --git a/resources/views/layouts/partial/footer.blade.php b/resources/views/layouts/partial/footer.blade.php index dfe3987d455b84e26bb1030baec94abe86f63b77..24e3fe3222f1a064645efcba76543bd9ff00fda2 100644 --- a/resources/views/layouts/partial/footer.blade.php +++ b/resources/views/layouts/partial/footer.blade.php @@ -1,3 +1,4 @@ +@if(config('instance.restricted.enabled') == false) <footer> <div class="container py-5"> <p class="d-flex flex-wrap justify-content-center mb-0 text-uppercase font-weight-bold small text-justify"> @@ -14,3 +15,4 @@ </p> </div> </footer> + @endif diff --git a/resources/views/layouts/partial/nav.blade.php b/resources/views/layouts/partial/nav.blade.php index 1f246f188875443bd027618f060868dfbfd52a0e..b5537b46986bfe9017b33572668134059446e894 100644 --- a/resources/views/layouts/partial/nav.blade.php +++ b/resources/views/layouts/partial/nav.blade.php @@ -1,107 +1,118 @@ -<nav class="navbar navbar-expand navbar-light navbar-laravel shadow-none border-bottom border sticky-top py-1"> +<nav class="navbar navbar-expand navbar-light navbar-laravel shadow-none border-bottom sticky-top py-1"> <div class="container"> - <a class="navbar-brand d-flex align-items-center" href="{{ route('timeline.personal') }}" title="Logo"> - <img src="/img/pixelfed-icon-color.svg" height="30px" class="px-2" loading="eager"> - <span class="font-weight-bold mb-0 d-none d-sm-block" style="font-size:20px;">{{ config('app.name', 'pixelfed') }}</span> - </a> + <a class="navbar-brand d-flex align-items-center" href="{{ route('timeline.personal') }}" title="Logo"> + <img src="/img/pixelfed-icon-color.svg" height="30px" class="px-2" loading="eager"> + <span class="font-weight-bold mb-0 d-none d-sm-block" style="font-size:20px;">{{ config('app.name', 'pixelfed') }}</span> + </a> - <div class="collapse navbar-collapse"> - @auth - <ul class="navbar-nav d-none d-md-block mx-auto"> - <form class="form-inline search-bar" method="get" action="/i/results"> - <input class="form-control form-control-sm" name="q" placeholder="{{__('navmenu.search')}}" aria-label="search" autocomplete="off" required style="line-height: 0.6;width:200px"> - </form> - </ul> - @endauth + <div class="collapse navbar-collapse"> + @auth + <ul class="navbar-nav d-none d-md-block mx-auto"> + <form class="form-inline search-bar" method="get" action="/i/results"> + <input class="form-control form-control-sm" name="q" placeholder="{{__('navmenu.search')}}" aria-label="search" autocomplete="off" required style="line-height: 0.6;width:200px"> + </form> + </ul> + @endauth - @guest - - <ul class="navbar-nav ml-auto"> - <li> - <a class="nav-link font-weight-bold text-primary" href="{{ route('login') }}" title="Login"> - {{ __('Login') }} - </a> - </li> - @if(config('pixelfed.open_registration')) + @guest + + <ul class="navbar-nav ml-auto"> <li> - <a class="nav-link font-weight-bold" href="{{ route('register') }}" title="Register"> - {{ __('Register') }} + <a class="nav-link font-weight-bold text-primary" href="{{ route('login') }}" title="Login"> + {{ __('Login') }} </a> </li> - @endif - @else - <div class="ml-auto"> - <ul class="navbar-nav"> - <div class="d-none d-md-block"> - <li class="nav-item px-md-2"> - <a class="nav-link font-weight-bold text-muted" href="/" title="Home Timeline" data-toggle="tooltip" data-placement="bottom"> - <i class="fas fa-home fa-lg"></i> + @if(config('pixelfed.open_registration') && config('instance.restricted.enabled') == false) + <li> + <a class="nav-link font-weight-bold" href="{{ route('register') }}" title="Register"> + {{ __('Register') }} </a> </li> - </div> - <li class="d-block d-md-none"></li> - <div class="d-none d-md-block"> - <li class="nav-item px-md-2"> - <a class="nav-link font-weight-bold text-muted" href="{{route('discover')}}" title="Discover" data-toggle="tooltip" data-placement="bottom"> - <i class="far fa-compass fa-lg"></i> + @endif + @else + <div class="ml-auto"> + <ul class="navbar-nav"> + <div class="d-none d-md-block"> + <li class="nav-item px-md-2"> + <a class="nav-link font-weight-bold text-muted" href="{{route('discover')}}" title="Discover" data-toggle="tooltip" data-placement="bottom"> + <i class="far fa-compass fa-lg"></i> + </a> + </li> + </div> + <div class="d-none d-md-block"> + <li class="nav-item px-md-2"> + <a class="nav-link font-weight-bold text-muted" href="/account/activity" title="Notifications" data-toggle="tooltip" data-placement="bottom"> + <i class="far fa-bell fa-lg"></i> + </a> + </li> + </div> + <li class="nav-item dropdown ml-2"> + <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="User Menu" data-toggle="tooltip" data-placement="bottom"> + <i class="far fa-user fa-lg text-muted"></i> </a> - </li> - </div> - <li class="nav-item dropdown ml-2"> - <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="User Menu" data-toggle="tooltip" data-placement="bottom"> - <i class="far fa-user fa-lg text-muted"></i> - </a> - <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> - <div class="dropdown-item font-weight-bold cursor-pointer" onclick="App.util.compose.post()"> - <span class="fas fa-camera-retro pr-1"></span> - {{__('navmenu.composePost')}} - </div> - <div class="dropdown-divider"></div> - <a class="dropdown-item font-weight-bold" href="/i/me"> - <span class="far fa-user pr-1"></span> - {{__('navmenu.myProfile')}} - </a> - <a class="d-block d-md-none dropdown-item font-weight-bold" href="{{route('discover')}}"> - <span class="far fa-compass pr-1"></span> - {{__('navmenu.discover')}} - </a> - <a class="dropdown-item font-weight-bold" href="{{route('notifications')}}"> - <span class="far fa-bell pr-1"></span> - Notifications - </a> - <div class="dropdown-divider"></div> - <a class="dropdown-item font-weight-bold" href="{{route('timeline.public')}}"> - <span class="far fa-map pr-1"></span> - {{__('navmenu.publicTimeline')}} - </a> - <div class="dropdown-divider"></div> - <a class="dropdown-item font-weight-bold" href="{{route('settings')}}"> - <span class="fas fa-cog pr-1"></span> - {{__('navmenu.settings')}} - </a> - @if(Auth::user()->is_admin == true) - <a class="dropdown-item font-weight-bold" href="{{ route('admin.home') }}"> - <span class="fas fa-cogs pr-1"></span> - {{__('navmenu.admin')}} - </a> - @endif - <div class="dropdown-divider"></div> - <a class="dropdown-item font-weight-bold" href="{{ route('logout') }}" - onclick="event.preventDefault(); - document.getElementById('logout-form').submit();"> - <span class="fas fa-sign-out-alt pr-1"></span> - {{ __('navmenu.logout') }} - </a> + <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> + <div class="dropdown-item font-weight-bold cursor-pointer" onclick="App.util.compose.post()"> + <span class="fas fa-plus-square pr-2 text-lighter"></span> + New Post + </div> + <div class="dropdown-divider"></div> + <a class="dropdown-item font-weight-bold" href="{{route('timeline.public')}}"> + <span class="fas fa-home pr-2 text-lighter"></span> + Home + </a> + <a class="dropdown-item font-weight-bold" href="{{route('timeline.public')}}"> + <span class="fas fa-stream pr-2 text-lighter"></span> + Local + </a> + {{-- <a class="dropdown-item font-weight-bold" href="#"> + <span class="fas fa-circle-notch pr-2 text-lighter"></span> + Circles + </a> --}} + {{-- <a class="dropdown-item font-weight-bold" href="{{route('timeline.public')}}"> + <span class="fas fa-project-diagram fa-sm pr-2 text-lighter"></span> + Network + </a> --}} + <div class="dropdown-divider"></div> + <a class="dropdown-item font-weight-bold" href="/i/me"> + <span class="far fa-user pr-2 text-lighter"></span> + {{__('navmenu.myProfile')}} + </a> + <a class="d-block d-md-none dropdown-item font-weight-bold" href="{{route('discover')}}"> + <span class="far fa-compass pr-2 text-lighter"></span> + {{__('navmenu.discover')}} + </a> + <a class="dropdown-item font-weight-bold" href="{{route('notifications')}}"> + <span class="far fa-bell pr-2 text-lighter"></span> + Notifications + </a> + <a class="dropdown-item font-weight-bold" href="{{route('settings')}}"> + <span class="fas fa-cog pr-2 text-lighter"></span> + {{__('navmenu.settings')}} + </a> + @if(Auth::user()->is_admin == true) + <div class="dropdown-divider"></div> + <a class="dropdown-item font-weight-bold" href="{{ route('admin.home') }}"> + <span class="fas fa-shield-alt fa-sm pr-2 text-lighter"></span> + {{__('navmenu.admin')}} + </a> + @endif + <div class="dropdown-divider"></div> + <a class="dropdown-item font-weight-bold" href="{{ route('logout') }}" + onclick="event.preventDefault(); + document.getElementById('logout-form').submit();"> + <span class="fas fa-sign-out-alt pr-2"></span> + {{ __('navmenu.logout') }} + </a> - <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> - @csrf - </form> - </div> - </li> - </div> - @endguest - </ul> - </div> + <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> + @csrf + </form> + </div> + </li> + </div> + @endguest + </ul> + </div> </div> -</nav> \ No newline at end of file +</nav> diff --git a/resources/views/profile/show.blade.php b/resources/views/profile/show.blade.php index ec78bf26d48e06f9bde3da6209e3b5822d1a0b54..61af9c12828a68a80c55871b89a5244be16123d0 100644 --- a/resources/views/profile/show.blade.php +++ b/resources/views/profile/show.blade.php @@ -11,6 +11,13 @@ @if($profile->website) <a class="d-none" href="{{$profile->website}}" rel="me">{{$profile->website}}</a> @endif + +<noscript> + <div class="container"> + <p class="pt-5 text-center lead">Please enable javascript to view this content.</p> + </div> +</noscript> + @endsection @push('meta')<meta property="og:description" content="{{$profile->bio}}"> @@ -22,20 +29,7 @@ @endif @endpush -@push('styles') -<style type="text/css"> - .navbar { - border: none !important; - } -</style> -@endpush +@push('scripts')<script type="text/javascript" src="{{ mix('js/profile.js') }}"></script> + <script type="text/javascript" defer>App.boot();</script> -@push('scripts') -<script type="text/javascript" src="{{ mix('js/profile.js') }}"></script> -<script type="text/javascript" src="{{ mix('js/compose.js') }}"></script> -<script type="text/javascript"> - new Vue({ - el: '#content' - }); -</script> @endpush diff --git a/resources/views/status/show.blade.php b/resources/views/status/show.blade.php index a68839d510a6b251c92c762fedcc32590d7a0287..73bf823091078d165a4324f919444dc3923e9715 100644 --- a/resources/views/status/show.blade.php +++ b/resources/views/status/show.blade.php @@ -2,10 +2,8 @@ @section('content') <noscript> - <div class="card"> - <div class="card-body container text-center font-weight-bold"> - This website requires javascript, please enable it and refresh the page. - </div> + <div class="container"> + <p class="pt-5 text-center lead">Please enable javascript to view this content.</p> </div> </noscript> <div class="mt-md-4"></div> diff --git a/resources/views/timeline/home.blade.php b/resources/views/timeline/home.blade.php index 69ce2f6886c9dc95d5e4eb6b3b0f07e011f84e2f..f16cab7a086d034cd15e63a5dcaeb4a70c8023ef 100644 --- a/resources/views/timeline/home.blade.php +++ b/resources/views/timeline/home.blade.php @@ -4,6 +4,12 @@ <timeline scope="home" layout="feed"></timeline> +<noscript> + <div class="container"> + <p class="pt-5 text-center lead">Please enable javascript to view this content.</p> + </div> +</noscript> + @endsection @push('scripts') diff --git a/resources/views/timeline/local.blade.php b/resources/views/timeline/local.blade.php index bbb8e872238b8a5e6508814450bc50530ca65291..3013aa8f0eda015d9d1015d077b529bd7439c6bb 100644 --- a/resources/views/timeline/local.blade.php +++ b/resources/views/timeline/local.blade.php @@ -4,14 +4,16 @@ <timeline scope="local" layout="feed"></timeline> +<noscript> + <div class="container"> + <p class="pt-5 text-center lead">Please enable javascript to view this content.</p> + </div> +</noscript> + @endsection @push('scripts') <script type="text/javascript" src="{{ mix('js/timeline.js') }}"></script> <script type="text/javascript" src="{{ mix('js/compose.js') }}"></script> -<script type="text/javascript"> - new Vue({ - el: '#content' - }); -</script> +<script type="text/javascript">window.App.boot()</script> @endpush \ No newline at end of file