mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-12 17:44:31 +00:00
Merge branch 'dev' of https://github.com/dansup/pixelfed into dev
This commit is contained in:
commit
83c6f4c615
11 changed files with 233 additions and 55 deletions
|
@ -6,10 +6,21 @@ use Illuminate\Http\Request;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use App\Mail\ConfirmEmail;
|
use App\Mail\ConfirmEmail;
|
||||||
use Auth, DB, Cache, Mail, Redis;
|
use Auth, DB, Cache, Mail, Redis;
|
||||||
use App\{EmailVerification, Notification, Profile, User};
|
use App\{
|
||||||
|
EmailVerification,
|
||||||
|
Notification,
|
||||||
|
Profile,
|
||||||
|
User,
|
||||||
|
UserFilter
|
||||||
|
};
|
||||||
|
|
||||||
class AccountController extends Controller
|
class AccountController extends Controller
|
||||||
{
|
{
|
||||||
|
protected $filters = [
|
||||||
|
'user.mute',
|
||||||
|
'user.block'
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
|
@ -134,4 +145,97 @@ class AccountController extends Controller
|
||||||
return $notifications;
|
return $notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function messages()
|
||||||
|
{
|
||||||
|
return view('account.messages');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function showMessage(Request $request, $id)
|
||||||
|
{
|
||||||
|
return view('account.message');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mute(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'type' => 'required|string',
|
||||||
|
'item' => 'required|integer|min:1'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = Auth::user()->profile;
|
||||||
|
$type = $request->input('type');
|
||||||
|
$item = $request->input('item');
|
||||||
|
$action = "{$type}.mute";
|
||||||
|
|
||||||
|
if(!in_array($action, $this->filters)) {
|
||||||
|
return abort(406);
|
||||||
|
}
|
||||||
|
$filterable = [];
|
||||||
|
switch ($type) {
|
||||||
|
case 'user':
|
||||||
|
$profile = Profile::findOrFail($item);
|
||||||
|
if($profile->id == $user->id) {
|
||||||
|
return abort(403);
|
||||||
|
}
|
||||||
|
$class = get_class($profile);
|
||||||
|
$filterable['id'] = $profile->id;
|
||||||
|
$filterable['type'] = $class;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
# code...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filter = UserFilter::firstOrCreate([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'filterable_id' => $filterable['id'],
|
||||||
|
'filterable_type' => $filterable['type'],
|
||||||
|
'filter_type' => 'mute'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function block(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'type' => 'required|string',
|
||||||
|
'item' => 'required|integer|min:1'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = Auth::user()->profile;
|
||||||
|
$type = $request->input('type');
|
||||||
|
$item = $request->input('item');
|
||||||
|
$action = "{$type}.block";
|
||||||
|
if(!in_array($action, $this->filters)) {
|
||||||
|
return abort(406);
|
||||||
|
}
|
||||||
|
$filterable = [];
|
||||||
|
switch ($type) {
|
||||||
|
case 'user':
|
||||||
|
$profile = Profile::findOrFail($item);
|
||||||
|
$class = get_class($profile);
|
||||||
|
$filterable['id'] = $profile->id;
|
||||||
|
$filterable['type'] = $class;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
# code...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filter = UserFilter::firstOrCreate([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'filterable_id' => $filterable['id'],
|
||||||
|
'filterable_type' => $filterable['type'],
|
||||||
|
'filter_type' => 'block'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,11 +51,22 @@ class RegisterController extends Controller
|
||||||
protected function validator(array $data)
|
protected function validator(array $data)
|
||||||
{
|
{
|
||||||
$this->validateUsername($data['username']);
|
$this->validateUsername($data['username']);
|
||||||
|
$usernameRules = [
|
||||||
|
'required',
|
||||||
|
'alpha_dash',
|
||||||
|
'min:2',
|
||||||
|
'max:15',
|
||||||
|
'unique:users',
|
||||||
|
function($attribute, $value, $fail) {
|
||||||
|
if(!ctype_alpha($value[0])) {
|
||||||
|
return $fail($attribute . ' is invalid. Username must be alpha-numeric and start with a letter.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
$rules = [
|
$rules = [
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'username' => 'required|alpha_dash|min:2|max:15|unique:users',
|
'username' => $usernameRules,
|
||||||
'email' => 'required|string|email|max:255|unique:users',
|
'email' => 'required|string|email|max:255|unique:users',
|
||||||
'password' => 'required|string|min:6|confirmed',
|
'password' => 'required|string|min:6|confirmed',
|
||||||
];
|
];
|
||||||
|
|
|
@ -18,7 +18,12 @@ class ProfileController extends Controller
|
||||||
public function show(Request $request, $username)
|
public function show(Request $request, $username)
|
||||||
{
|
{
|
||||||
$user = Profile::whereUsername($username)->firstOrFail();
|
$user = Profile::whereUsername($username)->firstOrFail();
|
||||||
$settings = User::whereUsername($username)->firstOrFail()->settings;
|
if($user->remote_url) {
|
||||||
|
$settings = new \StdClass;
|
||||||
|
$settings->crawlable = false;
|
||||||
|
} else {
|
||||||
|
$settings = User::whereUsername($username)->firstOrFail()->settings;
|
||||||
|
}
|
||||||
|
|
||||||
if($request->wantsJson() && config('pixelfed.activitypub_enabled')) {
|
if($request->wantsJson() && config('pixelfed.activitypub_enabled')) {
|
||||||
return $this->showActivityPub($request, $user);
|
return $this->showActivityPub($request, $user);
|
||||||
|
@ -37,6 +42,7 @@ class ProfileController extends Controller
|
||||||
$timeline = $user->statuses()
|
$timeline = $user->statuses()
|
||||||
->whereHas('media')
|
->whereHas('media')
|
||||||
->whereNull('in_reply_to_id')
|
->whereNull('in_reply_to_id')
|
||||||
|
->whereNull('reblog_of_id')
|
||||||
->orderBy('created_at','desc')
|
->orderBy('created_at','desc')
|
||||||
->withCount(['comments', 'likes'])
|
->withCount(['comments', 'likes'])
|
||||||
->simplePaginate(21);
|
->simplePaginate(21);
|
||||||
|
|
|
@ -44,29 +44,33 @@ class SettingsController extends Controller
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
$profile = $user->profile;
|
$profile = $user->profile;
|
||||||
|
|
||||||
|
$validate = config('pixelfed.enforce_email_verification');
|
||||||
|
|
||||||
if($user->email != $email) {
|
if($user->email != $email) {
|
||||||
$changes = true;
|
$changes = true;
|
||||||
$user->email = $email;
|
$user->email = $email;
|
||||||
$user->email_verified_at = null;
|
|
||||||
// Prevent old verifications from working
|
if($validate) {
|
||||||
EmailVerification::whereUserId($user->id)->delete();
|
$user->email_verified_at = null;
|
||||||
|
// Prevent old verifications from working
|
||||||
|
EmailVerification::whereUserId($user->id)->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only allow email to be updated if not yet verified
|
// Only allow email to be updated if not yet verified
|
||||||
if(!$changes && $user->email_verified_at) {
|
if(!$validate || !$changes && $user->email_verified_at) {
|
||||||
if($profile->name != $name) {
|
if($profile->name != $name) {
|
||||||
$changes = true;
|
$changes = true;
|
||||||
$user->name = $name;
|
$user->name = $name;
|
||||||
$profile->name = $name;
|
$profile->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($profile->website != $website) {
|
if(!$profile->website || $profile->website != $website) {
|
||||||
$changes = true;
|
$changes = true;
|
||||||
$profile->website = $website;
|
$profile->website = $website;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($profile->bio != $bio) {
|
if(!$profile->bio || !$profile->bio != $bio) {
|
||||||
$changes = true;
|
$changes = true;
|
||||||
$profile->bio = $bio;
|
$profile->bio = $bio;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +171,8 @@ class SettingsController extends Controller
|
||||||
$fields = [
|
$fields = [
|
||||||
'is_private',
|
'is_private',
|
||||||
'crawlable',
|
'crawlable',
|
||||||
|
'show_profile_follower_count',
|
||||||
|
'show_profile_following_count'
|
||||||
];
|
];
|
||||||
foreach($fields as $field) {
|
foreach($fields as $field) {
|
||||||
$form = $request->input($field);
|
$form = $request->input($field);
|
||||||
|
|
|
@ -6,5 +6,10 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class UserFilter extends Model
|
class UserFilter extends Model
|
||||||
{
|
{
|
||||||
//
|
protected $fillable = [
|
||||||
|
'user_id',
|
||||||
|
'filterable_id',
|
||||||
|
'filterable_type',
|
||||||
|
'filter_type'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class UpdateSettingsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('user_settings', function (Blueprint $table) {
|
||||||
|
$table->boolean('show_profile_followers')->default(true);
|
||||||
|
$table->boolean('show_profile_follower_count')->default(true);
|
||||||
|
$table->boolean('show_profile_following')->default(true);
|
||||||
|
$table->boolean('show_profile_following_count')->default(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$table->dropColumn('show_profile_followers');
|
||||||
|
$table->dropColumn('show_profile_follower_count');
|
||||||
|
$table->dropColumn('show_profile_following');
|
||||||
|
$table->dropColumn('show_profile_following_count');
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,27 +21,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tag-timeline">
|
||||||
<div class="tag-timeline row">
|
<div class="row">
|
||||||
@foreach($posts as $status)
|
@foreach($posts as $status)
|
||||||
<div class="col-4 p-0 p-sm-2 p-md-3">
|
<div class="col-4 p-0 p-sm-2 p-md-3">
|
||||||
<a class="card info-overlay card-md-border-0" href="{{$status->url()}}">
|
<a class="card info-overlay card-md-border-0" href="{{$status->url()}}">
|
||||||
<div class="square {{$status->firstMedia()->filter_class}}">
|
<div class="square {{$status->firstMedia()->filter_class}}">
|
||||||
<div class="square-content" style="background-image: url('{{$status->thumb()}}')"></div>
|
<div class="square-content" style="background-image: url('{{$status->thumb()}}')"></div>
|
||||||
<div class="info-overlay-text">
|
<div class="info-overlay-text">
|
||||||
<h5 class="text-white m-auto font-weight-bold">
|
<h5 class="text-white m-auto font-weight-bold">
|
||||||
<span class="pr-4">
|
<span class="pr-4">
|
||||||
<span class="far fa-heart fa-lg pr-1"></span> {{$status->likes_count}}
|
<span class="far fa-heart fa-lg pr-1"></span> {{$status->likes_count}}
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<span class="far fa-comment fa-lg pr-1"></span> {{$status->comments_count}}
|
<span class="far fa-comment fa-lg pr-1"></span> {{$status->comments_count}}
|
||||||
</span>
|
</span>
|
||||||
</h5>
|
</h5>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a>
|
||||||
</a>
|
</div>
|
||||||
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-center pagination-container mt-4">
|
<div class="d-flex justify-content-center pagination-container mt-4">
|
||||||
{{$posts->links()}}
|
{{$posts->links()}}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<li class="nav-item px-2">
|
<li class="nav-item px-2">
|
||||||
<div title="Create new post" data-toggle="tooltip" data-placement="bottom">
|
<div title="Create new post" data-toggle="tooltip" data-placement="bottom">
|
||||||
<a href="{{route('compose')}}" class="nav-link" data-toggle="modal" data-target="#composeModal">
|
<a href="{{route('compose')}}" class="nav-link" data-toggle="modal" data-target="#composeModal">
|
||||||
<i class="far fa-plus-square fa-lg text-primary"></i>
|
<i class="fas fa-camera-retro fa-lg text-primary"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<div class="profile-stats pb-3 d-inline-flex lead">
|
<div class="profile-stats pb-3 d-inline-flex lead">
|
||||||
<div class="font-weight-light pr-5">
|
<div class="font-weight-light pr-5">
|
||||||
<a class="text-dark" href="{{$user->url()}}">
|
<a class="text-dark" href="{{$user->url()}}">
|
||||||
<span class="font-weight-bold">{{$user->statuses()->whereNull('in_reply_to_id')->count()}}</span>
|
<span class="font-weight-bold">{{$user->statuses()->whereNull('reblog_of_id')->whereNull('in_reply_to_id')->count()}}</span>
|
||||||
Posts
|
Posts
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,13 +70,14 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="lead">
|
<p class="lead mb-0">
|
||||||
<span class="font-weight-bold">{{$user->name}}</span>
|
<span class="font-weight-bold">{{$user->name}}</span>
|
||||||
@if($user->remote_url)
|
@if($user->remote_url)
|
||||||
<span class="badge badge-info">REMOTE PROFILE</span>
|
<span class="badge badge-info">REMOTE PROFILE</span>
|
||||||
@endif
|
@endif
|
||||||
{{$user->bio}}
|
|
||||||
</p>
|
</p>
|
||||||
|
<p class="mb-0 lead">{{$user->bio}}</p>
|
||||||
|
<p class="mb-0"><a href="{{$user->website}}" class="font-weight-bold" rel="external nofollow noopener" target="_blank">{{str_limit($user->website, 30)}}</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Feature;
|
|
||||||
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
||||||
|
|
||||||
class ExampleTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* A basic test example.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function testBasicTest()
|
|
||||||
{
|
|
||||||
$response = $this->get('/');
|
|
||||||
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
}
|
|
29
tests/Feature/InstalledTest.php
Normal file
29
tests/Feature/InstalledTest.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
|
|
||||||
|
class InstalledTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testLandingTest()
|
||||||
|
{
|
||||||
|
$response = $this->get('/');
|
||||||
|
$response
|
||||||
|
->assertStatus(200)
|
||||||
|
->assertSeeText('Image Sharing for Everyone');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNodeinfoTest()
|
||||||
|
{
|
||||||
|
$response = $this->get('/.well-known/nodeinfo');
|
||||||
|
$response
|
||||||
|
->assertStatus(200)
|
||||||
|
->assertJson([
|
||||||
|
"links" => [
|
||||||
|
["rel" => "http://nodeinfo.diaspora.software/ns/schema/2.0"]
|
||||||
|
]]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue