commit
ab35ed3547
|
@ -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
|
||||
|
||||
|
|
49
app/Console/Commands/FailedJobGC.php
Normal file
49
app/Console/Commands/FailedJobGC.php
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
48
app/Console/Commands/PasswordResetGC.php
Normal file
48
app/Console/Commands/PasswordResetGC.php
Normal file
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
</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>
|
||||
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
|
||||
@csrf
|
||||
</form>
|
||||
@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>
|
||||
</li>
|
||||
</div>
|
||||
@endguest
|
||||
</ul>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</nav>
|
||||
</nav>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue