Merge pull request #666 from pixelfed/frontend-ui-refactor

v0.7.2
This commit is contained in:
daniel 2018-12-24 23:16:07 -07:00 committed by GitHub
commit ddfc868bb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 517 additions and 229 deletions

View File

@ -48,8 +48,8 @@ class FederationController extends Controller
{ {
$this->authCheck(); $this->authCheck();
$this->validate($request, [ $this->validate($request, [
'url' => 'required|string', 'url' => 'required|string',
]); ]);
if (config('pixelfed.remote_follow_enabled') !== true) { if (config('pixelfed.remote_follow_enabled') !== true) {
abort(403); abort(403);
@ -123,16 +123,15 @@ class FederationController extends Controller
{ {
$this->validate($request, ['resource'=>'required|string|min:3|max:255']); $this->validate($request, ['resource'=>'required|string|min:3|max:255']);
$hash = hash('sha256', $request->input('resource')); $resource = $request->input('resource');
$hash = hash('sha256', $resource);
$webfinger = Cache::remember('api:webfinger:'.$hash, 1440, function () use ($request) { $parsed = Nickname::normalizeProfileUrl($resource);
$resource = $request->input('resource'); $username = $parsed['username'];
$parsed = Nickname::normalizeProfileUrl($resource); $profile = Profile::whereUsername($username)->firstOrFail();
$username = $parsed['username']; if($profile->status != null) {
$user = Profile::whereUsername($username)->firstOrFail(); return ProfileController::accountCheck($profile);
}
return (new Webfinger($user))->generate(); $webfinger = (new Webfinger($profile))->generate();
});
return response()->json($webfinger, 200, [], JSON_PRETTY_PRINT); return response()->json($webfinger, 200, [], JSON_PRETTY_PRINT);
} }
@ -156,13 +155,16 @@ XML;
abort(403); abort(403);
} }
$user = Profile::whereNull('remote_url')->whereUsername($username)->firstOrFail(); $profile = Profile::whereNull('remote_url')->whereUsername($username)->firstOrFail();
if($user->is_private) { if($profile->status != null) {
return ProfileController::accountCheck($profile);
}
if($profile->is_private) {
return response()->json(['error'=>'403', 'msg' => 'private profile'], 403); return response()->json(['error'=>'403', 'msg' => 'private profile'], 403);
} }
$timeline = $user->statuses()->whereVisibility('public')->orderBy('created_at', 'desc')->paginate(10); $timeline = $profile->statuses()->whereVisibility('public')->orderBy('created_at', 'desc')->paginate(10);
$fractal = new Fractal\Manager(); $fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Item($user, new ProfileOutbox()); $resource = new Fractal\Resource\Item($profile, new ProfileOutbox());
$res = $fractal->createData($resource)->toArray(); $res = $fractal->createData($resource)->toArray();
return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json'); return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json');
@ -175,6 +177,9 @@ XML;
} }
$profile = Profile::whereNull('domain')->whereUsername($username)->firstOrFail(); $profile = Profile::whereNull('domain')->whereUsername($username)->firstOrFail();
if($profile->status != null) {
return ProfileController::accountCheck($profile);
}
$body = $request->getContent(); $body = $request->getContent();
$bodyDecoded = json_decode($body, true); $bodyDecoded = json_decode($body, true);
$signature = $request->header('signature'); $signature = $request->header('signature');
@ -205,6 +210,9 @@ XML;
->whereUsername($username) ->whereUsername($username)
->whereIsPrivate(false) ->whereIsPrivate(false)
->firstOrFail(); ->firstOrFail();
if($profile->status != null) {
return ProfileController::accountCheck($profile);
}
$obj = [ $obj = [
'@context' => 'https://www.w3.org/ns/activitystreams', '@context' => 'https://www.w3.org/ns/activitystreams',
'id' => $request->getUri(), 'id' => $request->getUri(),
@ -226,6 +234,9 @@ XML;
->whereUsername($username) ->whereUsername($username)
->whereIsPrivate(false) ->whereIsPrivate(false)
->firstOrFail(); ->firstOrFail();
if($profile->status != null) {
return ProfileController::accountCheck($profile);
}
$obj = [ $obj = [
'@context' => 'https://www.w3.org/ns/activitystreams', '@context' => 'https://www.w3.org/ns/activitystreams',
'id' => $request->getUri(), 'id' => $request->getUri(),

View File

@ -37,7 +37,7 @@ class FollowerController extends Controller
protected function handleFollowRequest($item) protected function handleFollowRequest($item)
{ {
$user = Auth::user()->profile; $user = Auth::user()->profile;
$target = Profile::where('id', '!=', $user->id)->findOrFail($item); $target = Profile::where('id', '!=', $user->id)->whereNull('status')->findOrFail($item);
$private = (bool) $target->is_private; $private = (bool) $target->is_private;
$blocked = UserFilter::whereUserId($target->id) $blocked = UserFilter::whereUserId($target->id)
->whereFilterType('block') ->whereFilterType('block')

View File

@ -112,6 +112,7 @@ class InternalApiController extends Controller
$people = Profile::select('id', 'name', 'username') $people = Profile::select('id', 'name', 'username')
->with('avatar') ->with('avatar')
->whereNull('status')
->orderByRaw('rand()') ->orderByRaw('rand()')
->whereHas('statuses') ->whereHas('statuses')
->whereNull('domain') ->whereNull('domain')
@ -206,6 +207,9 @@ class InternalApiController extends Controller
$posts = Status::select('id', 'caption', 'profile_id') $posts = Status::select('id', 'caption', 'profile_id')
->whereHas('media') ->whereHas('media')
->whereHas('profile', function($q) {
return $q->whereNull('status');
})
->whereIsNsfw(false) ->whereIsNsfw(false)
->whereVisibility('public') ->whereVisibility('public')
->whereNotIn('profile_id', $following) ->whereNotIn('profile_id', $following)

View File

@ -20,7 +20,11 @@ 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();
return $this->buildProfile($request, $user); if($user->status != null) {
return $this->accountCheck($user);
} else {
return $this->buildProfile($request, $user);
}
} }
// TODO: refactor this mess // TODO: refactor this mess
@ -31,6 +35,10 @@ class ProfileController extends Controller
$isPrivate = false; $isPrivate = false;
$isBlocked = false; $isBlocked = false;
if($user->status != null) {
return ProfileController::accountCheck($user);
}
if ($user->remote_url) { if ($user->remote_url) {
$settings = new \StdClass; $settings = new \StdClass;
$settings->crawlable = false; $settings->crawlable = false;
@ -118,8 +126,27 @@ class ProfileController extends Controller
return false; return false;
} }
public static function accountCheck(Profile $profile)
{
switch ($profile->status) {
case 'disabled':
case 'delete':
return view('profile.disabled');
break;
default:
# code...
break;
}
return abort(404);
}
public function showActivityPub(Request $request, $user) public function showActivityPub(Request $request, $user)
{ {
if($user->status != null) {
return ProfileController::accountCheck($user);
}
$fractal = new Fractal\Manager(); $fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Item($user, new ProfileTransformer); $resource = new Fractal\Resource\Item($user, new ProfileTransformer);
$res = $fractal->createData($resource)->toArray(); $res = $fractal->createData($resource)->toArray();
@ -129,6 +156,9 @@ class ProfileController extends Controller
public function showAtomFeed(Request $request, $user) public function showAtomFeed(Request $request, $user)
{ {
$profile = $user = Profile::whereUsername($user)->firstOrFail(); $profile = $user = Profile::whereUsername($user)->firstOrFail();
if($profile->status != null) {
return $this->accountCheck($profile);
}
if($profile->is_private || Auth::check()) { if($profile->is_private || Auth::check()) {
$blocked = $this->blockedProfileCheck($profile); $blocked = $this->blockedProfileCheck($profile);
$check = $this->privateProfileCheck($profile, null); $check = $this->privateProfileCheck($profile, null);
@ -144,7 +174,9 @@ class ProfileController extends Controller
public function followers(Request $request, $username) public function followers(Request $request, $username)
{ {
$profile = $user = Profile::whereUsername($username)->firstOrFail(); $profile = $user = Profile::whereUsername($username)->firstOrFail();
if($profile->status != null) {
return $this->accountCheck($profile);
}
// TODO: fix $profile/$user mismatch in profile & follower templates // TODO: fix $profile/$user mismatch in profile & follower templates
$owner = Auth::check() && Auth::id() === $user->user_id; $owner = Auth::check() && Auth::id() === $user->user_id;
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false; $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
@ -155,7 +187,7 @@ class ProfileController extends Controller
return view('profile.private', compact('user', 'is_following')); return view('profile.private', compact('user', 'is_following'));
} }
} }
$followers = $profile->followers()->orderBy('created_at', 'desc')->simplePaginate(12); $followers = $profile->followers()->whereNull('status')->orderBy('created_at', 'desc')->simplePaginate(12);
$is_admin = is_null($user->domain) ? $user->user->is_admin : false; $is_admin = is_null($user->domain) ? $user->user->is_admin : false;
if ($user->remote_url) { if ($user->remote_url) {
$settings = new \StdClass; $settings = new \StdClass;
@ -172,6 +204,9 @@ class ProfileController extends Controller
public function following(Request $request, $username) public function following(Request $request, $username)
{ {
$profile = $user = Profile::whereUsername($username)->firstOrFail(); $profile = $user = Profile::whereUsername($username)->firstOrFail();
if($profile->status != null) {
return $this->accountCheck($profile);
}
// TODO: fix $profile/$user mismatch in profile & follower templates // TODO: fix $profile/$user mismatch in profile & follower templates
$owner = Auth::check() && Auth::id() === $user->user_id; $owner = Auth::check() && Auth::id() === $user->user_id;
$is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false; $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
@ -182,7 +217,7 @@ class ProfileController extends Controller
return view('profile.private', compact('user', 'is_following')); return view('profile.private', compact('user', 'is_following'));
} }
} }
$following = $profile->following()->orderBy('created_at', 'desc')->simplePaginate(12); $following = $profile->following()->whereNull('status')->orderBy('created_at', 'desc')->simplePaginate(12);
$is_admin = is_null($user->domain) ? $user->user->is_admin : false; $is_admin = is_null($user->domain) ? $user->user->is_admin : false;
if ($user->remote_url) { if ($user->remote_url) {
$settings = new \StdClass; $settings = new \StdClass;
@ -201,7 +236,10 @@ class ProfileController extends Controller
if (Auth::check() === false || $username !== Auth::user()->username) { if (Auth::check() === false || $username !== Auth::user()->username) {
abort(403); abort(403);
} }
$user = Auth::user()->profile; $user = $profile = Auth::user()->profile;
if($profile->status != null) {
return $this->accountCheck($profile);
}
$settings = User::whereUsername($username)->firstOrFail()->settings; $settings = User::whereUsername($username)->firstOrFail()->settings;
$owner = true; $owner = true;
$following = false; $following = false;

View File

@ -43,6 +43,9 @@ class PublicApiController extends Controller
return []; return [];
} else { } else {
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
if($profile->status) {
return [];
}
$user = new Fractal\Resource\Item($profile, new AccountTransformer()); $user = new Fractal\Resource\Item($profile, new AccountTransformer());
return $this->fractal->createData($user)->toArray(); return $this->fractal->createData($user)->toArray();
} }
@ -54,6 +57,9 @@ class PublicApiController extends Controller
return []; return [];
} else { } else {
$profile = Auth::user()->profile; $profile = Auth::user()->profile;
if($profile->status) {
return [];
}
$likes = $status->likedBy()->orderBy('created_at','desc')->paginate(10); $likes = $status->likedBy()->orderBy('created_at','desc')->paginate(10);
$collection = new Fractal\Resource\Collection($likes, new AccountTransformer()); $collection = new Fractal\Resource\Collection($likes, new AccountTransformer());
return $this->fractal->createData($collection)->toArray(); return $this->fractal->createData($collection)->toArray();
@ -74,8 +80,8 @@ class PublicApiController extends Controller
public function status(Request $request, $username, int $postid) public function status(Request $request, $username, int $postid)
{ {
$profile = Profile::whereUsername($username)->first(); $profile = Profile::whereUsername($username)->whereNull('status')->firstOrFail();
$status = Status::whereProfileId($profile->id)->find($postid); $status = Status::whereProfileId($profile->id)->findOrFail($postid);
$this->scopeCheck($profile, $status); $this->scopeCheck($profile, $status);
$item = new Fractal\Resource\Item($status, new StatusTransformer()); $item = new Fractal\Resource\Item($status, new StatusTransformer());
$res = [ $res = [
@ -100,8 +106,8 @@ class PublicApiController extends Controller
'limit' => 'nullable|integer|min:5|max:50' 'limit' => 'nullable|integer|min:5|max:50'
]); ]);
$limit = $request->limit ?? 10; $limit = $request->limit ?? 10;
$profile = Profile::whereUsername($username)->first(); $profile = Profile::whereUsername($username)->whereNull('status')->firstOrFail();
$status = Status::whereProfileId($profile->id)->find($postId); $status = Status::whereProfileId($profile->id)->findOrFail($postId);
$this->scopeCheck($profile, $status); $this->scopeCheck($profile, $status);
if($request->filled('min_id') || $request->filled('max_id')) { if($request->filled('min_id') || $request->filled('max_id')) {
if($request->filled('min_id')) { if($request->filled('min_id')) {
@ -133,8 +139,8 @@ class PublicApiController extends Controller
public function statusLikes(Request $request, $username, $id) public function statusLikes(Request $request, $username, $id)
{ {
$profile = Profile::whereUsername($username)->first(); $profile = Profile::whereUsername($username)->whereNull('status')->firstOrFail();
$status = Status::whereProfileId($profile->id)->find($id); $status = Status::whereProfileId($profile->id)->findOrFail($id);
$this->scopeCheck($profile, $status); $this->scopeCheck($profile, $status);
$likes = $this->getLikes($status); $likes = $this->getLikes($status);
return response()->json([ return response()->json([
@ -144,8 +150,8 @@ class PublicApiController extends Controller
public function statusShares(Request $request, $username, $id) public function statusShares(Request $request, $username, $id)
{ {
$profile = Profile::whereUsername($username)->first(); $profile = Profile::whereUsername($username)->whereNull('status')->firstOrFail();
$status = Status::whereProfileId($profile->id)->find($id); $status = Status::whereProfileId($profile->id)->findOrFail($id);
$this->scopeCheck($profile, $status); $this->scopeCheck($profile, $status);
$shares = $this->getShares($status); $shares = $this->getShares($status);
return response()->json([ return response()->json([
@ -210,7 +216,7 @@ class PublicApiController extends Controller
// $timeline = Timeline::build()->local(); // $timeline = Timeline::build()->local();
$pid = Auth::user()->profile->id; $pid = Auth::user()->profile->id;
$private = Profile::whereIsPrivate(true)->where('id', '!=', $pid)->pluck('id'); $private = Profile::whereIsPrivate(true)->orWhereNotNull('status')->where('id', '!=', $pid)->pluck('id');
$filters = UserFilter::whereUserId($pid) $filters = UserFilter::whereUserId($pid)
->whereFilterableType('App\Profile') ->whereFilterableType('App\Profile')
->whereIn('filter_type', ['mute', 'block']) ->whereIn('filter_type', ['mute', 'block'])
@ -272,7 +278,7 @@ class PublicApiController extends Controller
$following = Follower::whereProfileId($pid)->pluck('following_id'); $following = Follower::whereProfileId($pid)->pluck('following_id');
$following->push($pid)->toArray(); $following->push($pid)->toArray();
$private = Profile::whereIsPrivate(true)->where('id', '!=', $pid)->pluck('id'); $private = Profile::whereIsPrivate(true)->orWhereNotNull('status')->where('id', '!=', $pid)->pluck('id');
$filters = UserFilter::whereUserId($pid) $filters = UserFilter::whereUserId($pid)
->whereFilterableType('App\Profile') ->whereFilterableType('App\Profile')
->whereIn('filter_type', ['mute', 'block']) ->whereIn('filter_type', ['mute', 'block'])

View File

@ -22,7 +22,7 @@ class SearchController extends Controller
return; return;
} }
$hash = hash('sha256', $tag); $hash = hash('sha256', $tag);
$tokens = Cache::remember('api:search:tag:'.$hash, 60, function () use ($tag) { $tokens = Cache::remember('api:search:tag:'.$hash, 5, function () use ($tag) {
$tokens = collect([]); $tokens = collect([]);
$hashtags = Hashtag::select('id', 'name', 'slug')->where('slug', 'like', '%'.$tag.'%')->limit(20)->get(); $hashtags = Hashtag::select('id', 'name', 'slug')->where('slug', 'like', '%'.$tag.'%')->limit(20)->get();
if($hashtags->count() > 0) { if($hashtags->count() > 0) {
@ -39,6 +39,7 @@ class SearchController extends Controller
$tokens->push($tags); $tokens->push($tags);
} }
$users = Profile::select('username', 'name', 'id') $users = Profile::select('username', 'name', 'id')
->whereNull('status')
->where('username', 'like', '%'.$tag.'%') ->where('username', 'like', '%'.$tag.'%')
->limit(20) ->limit(20)
->get(); ->get();

View File

@ -5,10 +5,8 @@ namespace App\Http\Controllers;
use App\AccountLog; use App\AccountLog;
use App\Following; use App\Following;
use App\UserFilter; use App\UserFilter;
use Auth; use Auth, DB, Cache, Purify;
use DB; use Carbon\Carbon;
use Cache;
use Purify;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Http\Controllers\Settings\{ use App\Http\Controllers\Settings\{
HomeSettings, HomeSettings,
@ -137,6 +135,18 @@ class SettingsController extends Controller
return view('settings.remove.temporary'); return view('settings.remove.temporary');
} }
public function removeAccountTemporarySubmit(Request $request)
{
$user = Auth::user();
$profile = $user->profile;
$user->status = 'disabled';
$profile->status = 'disabled';
$user->save();
$profile->save();
Auth::logout();
return redirect('/');
}
public function removeAccountPermanent(Request $request) public function removeAccountPermanent(Request $request)
{ {
return view('settings.remove.permanent'); return view('settings.remove.permanent');
@ -148,7 +158,14 @@ class SettingsController extends Controller
if($user->is_admin == true) { if($user->is_admin == true) {
return abort(400, 'You cannot delete an admin account.'); return abort(400, 'You cannot delete an admin account.');
} }
DeleteAccountPipeline::dispatch($user); $profile = $user->profile;
$ts = Carbon::now()->addMonth();
$user->status = 'delete';
$profile->status = 'delete';
$user->delete_after = $ts;
$profile->delete_after = $ts;
$user->save();
$profile->save();
Auth::logout(); Auth::logout();
return redirect('/'); return redirect('/');
} }

View File

@ -21,10 +21,22 @@ class StatusController extends Controller
{ {
$user = Profile::whereUsername($username)->firstOrFail(); $user = Profile::whereUsername($username)->firstOrFail();
if($user->status != null) {
return ProfileController::accountCheck($user);
}
$status = Status::whereProfileId($user->id) $status = Status::whereProfileId($user->id)
->whereNotIn('visibility',['draft','direct']) ->whereNotIn('visibility',['draft','direct'])
->findOrFail($id); ->findOrFail($id);
if($status->uri) {
$url = $status->uri;
if(ends_with($url, '/activity')) {
$url = str_replace('/activity', '', $url);
}
return redirect($url);
}
if($status->visibility == 'private' || $user->is_private) { if($status->visibility == 'private' || $user->is_private) {
if(!Auth::check()) { if(!Auth::check()) {
abort(403); abort(403);

View File

@ -37,11 +37,9 @@ class NewStatusPipeline implements ShouldQueue
$status = $this->status; $status = $this->status;
StatusEntityLexer::dispatch($status); StatusEntityLexer::dispatch($status);
StatusActivityPubDeliver::dispatch($status);
Cache::forever('post.'.$status->id, $status); // Cache::forever('post.'.$status->id, $status);
// $redis = Redis::connection();
$redis = Redis::connection(); // $redis->lpush(config('cache.prefix').':user.'.$status->profile_id.'.posts', $status->id);
$redis->lpush(config('cache.prefix').':user.'.$status->profile_id.'.posts', $status->id);
} }
} }

View File

@ -38,6 +38,10 @@ class StatusActivityPubDeliver implements ShouldQueue
{ {
$status = $this->status; $status = $this->status;
if($status->local == true || $status->url || $status->uri) {
return;
}
$audience = $status->profile->getAudienceInbox(); $audience = $status->profile->getAudienceInbox();
$profile = $status->profile; $profile = $status->profile;
@ -49,7 +53,5 @@ class StatusActivityPubDeliver implements ShouldQueue
foreach($audience as $url) { foreach($audience as $url) {
Helpers::sendSignedObject($profile, $url, $activity); Helpers::sendSignedObject($profile, $url, $activity);
} }
// todo: fanout on write
} }
} }

View File

@ -42,7 +42,6 @@ class StatusEntityLexer implements ShouldQueue
*/ */
public function handle() public function handle()
{ {
$status = $this->status;
$this->parseEntities(); $this->parseEntities();
} }
@ -73,6 +72,7 @@ class StatusEntityLexer implements ShouldQueue
$status->entities = json_encode($this->entities); $status->entities = json_encode($this->entities);
$status->save(); $status->save();
}); });
StatusActivityPubDeliver::dispatch($this->status);
} }
public function storeHashtags() public function storeHashtags()

View File

@ -61,5 +61,30 @@ class AuthLogin
CreateAvatar::dispatch($profile); CreateAvatar::dispatch($profile);
}); });
} }
if($user->status != null) {
$profile = $user->profile;
switch ($user->status) {
case 'disabled':
$profile->status = null;
$user->status = null;
$profile->save();
$user->save();
break;
case 'delete':
$profile->status = null;
$profile->delete_after = null;
$user->status = null;
$user->delete_after = null;
$profile->save();
$user->save();
break;
default:
# code...
break;
}
}
} }
} }

View File

@ -7,6 +7,7 @@ use App\{
Activity, Activity,
Follower, Follower,
Like, Like,
Media,
Notification, Notification,
Profile, Profile,
Status Status
@ -281,11 +282,11 @@ class Helpers {
public static function profileFirstOrNew($url, $runJobs = false) public static function profileFirstOrNew($url, $runJobs = false)
{ {
$res = self::fetchProfileFromUrl($url); $res = self::fetchProfileFromUrl($url);
$domain = parse_url($res['url'], PHP_URL_HOST); $domain = parse_url($res['id'], PHP_URL_HOST);
$username = $res['preferredUsername']; $username = $res['preferredUsername'];
$remoteUsername = "@{$username}@{$domain}"; $remoteUsername = "@{$username}@{$domain}";
$profile = Profile::whereRemoteUrl($res['url'])->first(); $profile = Profile::whereRemoteUrl($res['id'])->first();
if(!$profile) { if(!$profile) {
$profile = new Profile; $profile = new Profile;
$profile->domain = $domain; $profile->domain = $domain;
@ -295,7 +296,7 @@ class Helpers {
$profile->sharedInbox = isset($res['endpoints']) && isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : null; $profile->sharedInbox = isset($res['endpoints']) && isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : null;
$profile->inbox_url = $res['inbox']; $profile->inbox_url = $res['inbox'];
$profile->outbox_url = $res['outbox']; $profile->outbox_url = $res['outbox'];
$profile->remote_url = $res['url']; $profile->remote_url = $res['id'];
$profile->public_key = $res['publicKey']['publicKeyPem']; $profile->public_key = $res['publicKey']['publicKeyPem'];
$profile->key_id = $res['publicKey']['id']; $profile->key_id = $res['publicKey']['id'];
$profile->save(); $profile->save();

View File

@ -32,7 +32,7 @@ class Inbox
public function handle() public function handle()
{ {
$this->authenticatePayload(); $this->handleVerb();
} }
public function authenticatePayload() public function authenticatePayload()
@ -142,16 +142,11 @@ class Inbox
$activity = $this->payload['object']; $activity = $this->payload['object'];
$actor = $this->actorFirstOrCreate($this->payload['actor']); $actor = $this->actorFirstOrCreate($this->payload['actor']);
$inReplyTo = $activity['inReplyTo']; $inReplyTo = $activity['inReplyTo'];
$url = $activity['id'];
if(!Helpers::statusFirstOrFetch($activity['url'], true)) { if(!Helpers::statusFirstOrFetch($url, true)) {
$this->logger->delete();
return; return;
} }
$this->logger->to_id = $this->profile->id;
$this->logger->from_id = $actor->id;
$this->logger->processed_at = Carbon::now();
$this->logger->save();
} }
public function handleNoteCreate() public function handleNoteCreate()
@ -164,12 +159,11 @@ class Inbox
if(Helpers::userInAudience($this->profile, $this->payload) == false) { if(Helpers::userInAudience($this->profile, $this->payload) == false) {
//Log::error('AP:inbox:userInAudience:false - Activity#'.$this->logger->id); //Log::error('AP:inbox:userInAudience:false - Activity#'.$this->logger->id);
$logger = Activity::find($this->logger->id);
$logger->delete();
return; return;
} }
if(Status::whereUrl($activity['url'])->exists()) { $url = $activity['id'];
if(Status::whereUrl($url)->exists()) {
return; return;
} }
@ -178,18 +172,12 @@ class Inbox
$status->profile_id = $actor->id; $status->profile_id = $actor->id;
$status->caption = strip_tags($activity['content']); $status->caption = strip_tags($activity['content']);
$status->visibility = $status->scope = 'public'; $status->visibility = $status->scope = 'public';
$status->url = $activity['url']; $status->url = $url;
$status->save(); $status->save();
return $status; return $status;
}); });
Helpers::importNoteAttachment($activity, $status); Helpers::importNoteAttachment($activity, $status);
$logger = Activity::find($this->logger->id);
$logger->to_id = $this->profile->id;
$logger->from_id = $actor->id;
$logger->processed_at = Carbon::now();
$logger->save();
} }
public function handleFollowActivity() public function handleFollowActivity()
@ -214,7 +202,6 @@ class Inbox
'local_profile' => empty($actor->domain) 'local_profile' => empty($actor->domain)
]); ]);
if($follower->wasRecentlyCreated == false) { if($follower->wasRecentlyCreated == false) {
$this->logger->delete();
return; return;
} }
// send notification // send notification
@ -228,37 +215,53 @@ class Inbox
$notification->item_type = "App\Profile"; $notification->item_type = "App\Profile";
$notification->save(); $notification->save();
\Cache::forever('notification.'.$notification->id, $notification);
$redis = Redis::connection();
$nkey = config('cache.prefix').':user.'.$target->id.'.notifications';
$redis->lpush($nkey, $notification->id);
// send Accept to remote profile // send Accept to remote profile
$accept = [ $accept = [
'@context' => 'https://www.w3.org/ns/activitystreams', '@context' => 'https://www.w3.org/ns/activitystreams',
'id' => $follower->permalink('/accept'), 'id' => $target->permalink().'#accepts/follows/',
'type' => 'Accept', 'type' => 'Accept',
'actor' => $target->permalink(), 'actor' => $target->permalink(),
'object' => [ 'object' => [
'id' => $this->payload['id'], 'id' => $actor->permalink('#follows/'.$target->id),
'type' => 'Follow', 'type' => 'Follow',
'actor' => $target->permalink(), 'actor' => $actor->permalink(),
'object' => $actor->permalink() 'object' => $target->permalink()
] ]
]; ];
Helpers::sendSignedObject($target, $actor->inbox_url, $accept); Helpers::sendSignedObject($target, $actor->inbox_url, $accept);
} }
$this->logger->to_id = $target->id;
$this->logger->from_id = $actor->id;
$this->logger->processed_at = Carbon::now();
$this->logger->save();
} }
public function handleAnnounceActivity() public function handleAnnounceActivity()
{ {
$actor = $this->actorFirstOrCreate($this->payload['actor']);
$activity = $this->payload['object'];
if(!$actor || $actor->domain == null) {
return;
}
if(Helpers::validateLocalUrl($activity) == false) {
return;
}
$parent = Helpers::statusFirstOrFetch($activity, true);
if(!$parent) {
return;
}
$status = Status::firstOrCreate([
'profile_id' => $actor->id,
'in_reply_to_id' => $parent->id,
'type' => 'reply'
]);
if($status->wasRecentlyCreated) {
$notification = new Notification();
$notification->profile_id = $parent->profile->id;
$notification->actor_id = $actor->id;
$notification->action = 'comment';
$notification->message = $status->toText();
$notification->rendered = $status->toHtml();
$notification->item_id = $parent->id;
$notification->item_type = "App\Status";
$notification->save();
}
} }
public function handleAcceptActivity() public function handleAcceptActivity()
@ -268,7 +271,19 @@ class Inbox
public function handleDeleteActivity() public function handleDeleteActivity()
{ {
$actor = $this->payload['actor'];
$obj = $this->payload['object'];
if(is_string($obj) && Helpers::validateUrl($obj)) {
// actor object detected
} else if (is_array($obj) && isset($obj['type']) && $obj['type'] == 'Tombstone') {
// tombstone detected
$status = Status::whereUri($obj['id'])->first();
if($status == null) {
return;
}
$status->forceDelete();
}
} }
public function handleLikeActivity() public function handleLikeActivity()
@ -289,10 +304,6 @@ class Inbox
return; return;
} }
LikePipeline::dispatch($like); LikePipeline::dispatch($like);
$this->logger->to_id = $status->profile_id;
$this->logger->from_id = $profile->id;
$this->logger->processed_at = Carbon::now();
$this->logger->save();
} }
@ -306,19 +317,29 @@ class Inbox
$actor = $this->payload['actor']; $actor = $this->payload['actor'];
$profile = self::actorFirstOrCreate($actor); $profile = self::actorFirstOrCreate($actor);
$obj = $this->payload['object']; $obj = $this->payload['object'];
$status = Helpers::statusFirstOrFetch($obj['object']);
switch ($obj['type']) { switch ($obj['type']) {
case 'Like': case 'Like':
$status = Helpers::statusFirstOrFetch($obj['object']);
Like::whereProfileId($profile->id) Like::whereProfileId($profile->id)
->whereStatusId($status->id) ->whereStatusId($status->id)
->delete(); ->forceDelete();
break;
case 'Announce':
$parent = Helpers::statusFirstOrFetch($obj['object']);
$status = Status::whereProfileId($profile->id)
->whereReblogOfId($parent->id)
->first();
Notification::whereProfileId($parent->profile->id)
->whereActorId($profile->id)
->whereAction('share')
->whereItemId($status->id)
->whereItemType('App\Status')
->forceDelete();
$status->forceDelete();
break; break;
} }
$this->logger->to_id = $status->profile_id;
$this->logger->from_id = $profile->id;
$this->logger->processed_at = Carbon::now();
$this->logger->save();
} }
} }

View File

@ -0,0 +1,40 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddDeleteAfterToUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('profiles', function (Blueprint $table) {
$table->timestamp('delete_after')->nullable();
});
Schema::table('users', function (Blueprint $table) {
$table->timestamp('delete_after')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('profiles', function (Blueprint $table) {
$table->dropColumn('delete_after');
});
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('delete_after');
});
}
}

245
package-lock.json generated
View File

@ -104,11 +104,15 @@
"json-schema-traverse": "^0.3.0" "json-schema-traverse": "^0.3.0"
} }
}, },
"ajv-errors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ=="
},
"ajv-keywords": { "ajv-keywords": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
"dev": true
}, },
"align-text": { "align-text": {
"version": "0.1.4", "version": "0.1.4",
@ -164,7 +168,6 @@
"version": "3.2.1", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": { "requires": {
"color-convert": "^1.9.0" "color-convert": "^1.9.0"
} }
@ -199,7 +202,6 @@
"version": "1.0.10", "version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": { "requires": {
"sprintf-js": "~1.0.2" "sprintf-js": "~1.0.2"
} }
@ -632,6 +634,11 @@
"babel-types": "^6.24.1" "babel-types": "^6.24.1"
} }
}, },
"babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
"integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
},
"babel-helpers": { "babel-helpers": {
"version": "6.24.1", "version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
@ -1243,8 +1250,7 @@
"big.js": { "big.js": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
"dev": true
}, },
"binary-extensions": { "binary-extensions": {
"version": "1.11.0", "version": "1.11.0",
@ -1253,9 +1259,9 @@
"dev": true "dev": true
}, },
"blob": { "blob": {
"version": "0.0.4", "version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
}, },
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
@ -1328,9 +1334,9 @@
} }
}, },
"bootstrap": { "bootstrap": {
"version": "4.1.3", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.2.1.tgz",
"integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==" "integrity": "sha512-tt/7vIv3Gm2mnd/WeDx36nfGGHleil0Wg8IeB7eMrVkY0fZ5iTaBisSh8oNANc2IBsCc6vCgCNTIM/IEN0+50Q=="
}, },
"bootstrap-vue": { "bootstrap-vue": {
"version": "2.0.0-rc.11", "version": "2.0.0-rc.11",
@ -1651,7 +1657,6 @@
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"requires": { "requires": {
"ansi-styles": "^3.2.1", "ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5", "escape-string-regexp": "^1.0.5",
@ -1884,7 +1889,6 @@
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": { "requires": {
"color-name": "1.1.3" "color-name": "1.1.3"
} }
@ -1892,8 +1896,7 @@
"color-name": { "color-name": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
"dev": true
}, },
"color-string": { "color-string": {
"version": "0.3.0", "version": "0.3.0",
@ -2123,7 +2126,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
"integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
"dev": true,
"requires": { "requires": {
"is-directory": "^0.3.1", "is-directory": "^0.3.1",
"js-yaml": "^3.9.0", "js-yaml": "^3.9.0",
@ -2134,14 +2136,12 @@
"esprima": { "esprima": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
"dev": true
}, },
"js-yaml": { "js-yaml": {
"version": "3.12.0", "version": "3.12.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
"dev": true,
"requires": { "requires": {
"argparse": "^1.0.7", "argparse": "^1.0.7",
"esprima": "^4.0.0" "esprima": "^4.0.0"
@ -2151,7 +2151,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": { "requires": {
"error-ex": "^1.3.1", "error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1" "json-parse-better-errors": "^1.0.1"
@ -2842,11 +2841,72 @@
"minimalistic-crypto-utils": "^1.0.0" "minimalistic-crypto-utils": "^1.0.0"
} }
}, },
"emoji-mart-vue": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/emoji-mart-vue/-/emoji-mart-vue-2.6.6.tgz",
"integrity": "sha512-844CI/Sa99G6goiZN6u+zT5XxB4wUhpYYTK8s3FrU2fl9y0ckbqe0uw7EuY0R53hb4bo9uJHVOPywE+C4vu4fg==",
"requires": {
"postcss-loader": "^3.0.0"
},
"dependencies": {
"ajv": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"postcss": {
"version": "7.0.7",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
"integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
"requires": {
"chalk": "^2.4.1",
"source-map": "^0.6.1",
"supports-color": "^5.5.0"
}
},
"postcss-loader": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
"integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
"requires": {
"loader-utils": "^1.1.0",
"postcss": "^7.0.0",
"postcss-load-config": "^2.0.0",
"schema-utils": "^1.0.0"
}
},
"schema-utils": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
"integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
"requires": {
"ajv": "^6.1.0",
"ajv-errors": "^1.0.0",
"ajv-keywords": "^3.1.0"
}
}
}
},
"emojis-list": { "emojis-list": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
"dev": true
}, },
"encodeurl": { "encodeurl": {
"version": "1.0.2", "version": "1.0.2",
@ -2872,9 +2932,9 @@
} }
}, },
"engine.io-client": { "engine.io-client": {
"version": "3.2.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.1.tgz",
"integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "integrity": "sha512-q66JBFuQcy7CSlfAz9L3jH+v7DTT3i6ZEadYcVj2pOs8/0uJHLxKX3WBkGTvULJMdz0tUCyJag0aKT/dpXL9BQ==",
"requires": { "requires": {
"component-emitter": "1.2.1", "component-emitter": "1.2.1",
"component-inherit": "0.0.3", "component-inherit": "0.0.3",
@ -2884,20 +2944,20 @@
"indexof": "0.0.1", "indexof": "0.0.1",
"parseqs": "0.0.5", "parseqs": "0.0.5",
"parseuri": "0.0.5", "parseuri": "0.0.5",
"ws": "~3.3.1", "ws": "~6.1.0",
"xmlhttprequest-ssl": "~1.5.4", "xmlhttprequest-ssl": "~1.5.4",
"yeast": "0.1.2" "yeast": "0.1.2"
} }
}, },
"engine.io-parser": { "engine.io-parser": {
"version": "2.1.2", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
"integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
"requires": { "requires": {
"after": "0.8.2", "after": "0.8.2",
"arraybuffer.slice": "~0.0.7", "arraybuffer.slice": "~0.0.7",
"base64-arraybuffer": "0.1.5", "base64-arraybuffer": "0.1.5",
"blob": "0.0.4", "blob": "0.0.5",
"has-binary2": "~1.0.2" "has-binary2": "~1.0.2"
} }
}, },
@ -2926,7 +2986,6 @@
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
"requires": { "requires": {
"is-arrayish": "^0.2.1" "is-arrayish": "^0.2.1"
} }
@ -3458,8 +3517,7 @@
"fast-json-stable-stringify": { "fast-json-stable-stringify": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
"dev": true
}, },
"fastparse": { "fastparse": {
"version": "1.1.1", "version": "1.1.1",
@ -4563,8 +4621,7 @@
"has-flag": { "has-flag": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
"dev": true
}, },
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
@ -4945,7 +5002,6 @@
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
"integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
"dev": true,
"requires": { "requires": {
"import-from": "^2.1.0" "import-from": "^2.1.0"
} }
@ -4954,7 +5010,6 @@
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
"integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
"dev": true,
"requires": { "requires": {
"resolve-from": "^3.0.0" "resolve-from": "^3.0.0"
} }
@ -5141,8 +5196,7 @@
"is-arrayish": { "is-arrayish": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
"dev": true
}, },
"is-binary-path": { "is-binary-path": {
"version": "1.0.1", "version": "1.0.1",
@ -5222,8 +5276,7 @@
"is-directory": { "is-directory": {
"version": "0.3.1", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
"dev": true
}, },
"is-dotfile": { "is-dotfile": {
"version": "1.0.3", "version": "1.0.3",
@ -5477,8 +5530,7 @@
"json-parse-better-errors": { "json-parse-better-errors": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
"dev": true
}, },
"json-schema": { "json-schema": {
"version": "0.2.3", "version": "0.2.3",
@ -5507,8 +5559,7 @@
"json5": { "json5": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
"dev": true
}, },
"jsonfile": { "jsonfile": {
"version": "3.0.1", "version": "3.0.1",
@ -5544,9 +5595,9 @@
"dev": true "dev": true
}, },
"laravel-echo": { "laravel-echo": {
"version": "1.4.0", "version": "1.5.2",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.4.0.tgz", "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.5.2.tgz",
"integrity": "sha512-O0vkToCCpxuH9dYAlugTLQzG0BmxvGrjXim0LHZ0VPsFu/Y+sXnV9GvYbmcBq1rcJymQc/6GHMUCDY01lN26lQ==" "integrity": "sha512-Xw9QsxJKapv0C2UTnXRRIM1+epL3+qaSRGd7V8pXEuIHnxjcdpk2I7YLauDzYhBNMKEKWtlE/sv9Wgs+hYKnbg=="
}, },
"laravel-mix": { "laravel-mix": {
"version": "2.1.14", "version": "2.1.14",
@ -5638,7 +5689,6 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
"dev": true,
"requires": { "requires": {
"big.js": "^3.1.3", "big.js": "^3.1.3",
"emojis-list": "^2.0.0", "emojis-list": "^2.0.0",
@ -6642,6 +6692,11 @@
} }
} }
}, },
"opencollective-postinstall": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.1.tgz",
"integrity": "sha512-saQQ9hjLwu/oS0492eyYotoh+bra1819cfAT5rjY/e4REWwuc8IgZ844Oo44SiftWcJuBiqp0SA0BFVbmLX0IQ=="
},
"opn": { "opn": {
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
@ -6964,9 +7019,9 @@
} }
}, },
"popper.js": { "popper.js": {
"version": "1.14.4", "version": "1.14.6",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz",
"integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY=" "integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA=="
}, },
"portfinder": { "portfinder": {
"version": "1.0.17", "version": "1.0.17",
@ -7662,7 +7717,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
"integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==",
"dev": true,
"requires": { "requires": {
"cosmiconfig": "^4.0.0", "cosmiconfig": "^4.0.0",
"import-cwd": "^2.0.0" "import-cwd": "^2.0.0"
@ -9591,8 +9645,7 @@
"require-from-string": { "require-from-string": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
"dev": true
}, },
"require-main-filename": { "require-main-filename": {
"version": "1.0.1", "version": "1.0.1",
@ -9627,8 +9680,7 @@
"resolve-from": { "resolve-from": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
"dev": true
}, },
"resolve-url": { "resolve-url": {
"version": "0.2.1", "version": "0.2.1",
@ -9759,7 +9811,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
}, },
"safe-regex": { "safe-regex": {
"version": "1.1.0", "version": "1.1.0",
@ -10208,30 +10261,30 @@
} }
}, },
"socket.io-client": { "socket.io-client": {
"version": "2.1.1", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz",
"integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==",
"requires": { "requires": {
"backo2": "1.0.2", "backo2": "1.0.2",
"base64-arraybuffer": "0.1.5", "base64-arraybuffer": "0.1.5",
"component-bind": "1.0.0", "component-bind": "1.0.0",
"component-emitter": "1.2.1", "component-emitter": "1.2.1",
"debug": "~3.1.0", "debug": "~3.1.0",
"engine.io-client": "~3.2.0", "engine.io-client": "~3.3.1",
"has-binary2": "~1.0.2", "has-binary2": "~1.0.2",
"has-cors": "1.1.0", "has-cors": "1.1.0",
"indexof": "0.0.1", "indexof": "0.0.1",
"object-component": "0.0.3", "object-component": "0.0.3",
"parseqs": "0.0.5", "parseqs": "0.0.5",
"parseuri": "0.0.5", "parseuri": "0.0.5",
"socket.io-parser": "~3.2.0", "socket.io-parser": "~3.3.0",
"to-array": "0.1.4" "to-array": "0.1.4"
} }
}, },
"socket.io-parser": { "socket.io-parser": {
"version": "3.2.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
"integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
"requires": { "requires": {
"component-emitter": "1.2.1", "component-emitter": "1.2.1",
"debug": "~3.1.0", "debug": "~3.1.0",
@ -10307,8 +10360,7 @@
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
"dev": true
}, },
"source-map-resolve": { "source-map-resolve": {
"version": "0.5.2", "version": "0.5.2",
@ -10441,8 +10493,7 @@
"sprintf-js": { "sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
"dev": true
}, },
"sshpk": { "sshpk": {
"version": "1.14.2", "version": "1.14.2",
@ -10636,7 +10687,6 @@
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": { "requires": {
"has-flag": "^3.0.0" "has-flag": "^3.0.0"
} }
@ -10657,9 +10707,9 @@
} }
}, },
"sweetalert": { "sweetalert": {
"version": "2.1.0", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.0.tgz", "resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.2.tgz",
"integrity": "sha512-9YKj0SvjKyBfRWco50UOsIbXVeifYbxzT9Qda7EsqC01eafHGCSG0IR7g942ufjzt7lnwO8ZZBwr6emXv2fQrg==", "integrity": "sha512-iWx7X4anRBNDa/a+AdTmvAzQtkN1+s4j/JJRWlHpYE8Qimkohs8/XnFcWeYHH2lMA8LRCa5tj2d244If3S/hzA==",
"requires": { "requires": {
"es6-object-assign": "^1.1.0", "es6-object-assign": "^1.1.0",
"promise-polyfill": "^6.0.2" "promise-polyfill": "^6.0.2"
@ -10989,11 +11039,6 @@
} }
} }
}, },
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"union-value": { "union-value": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
@ -11127,7 +11172,6 @@
"version": "4.2.2", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"dev": true,
"requires": { "requires": {
"punycode": "^2.1.0" "punycode": "^2.1.0"
}, },
@ -11135,8 +11179,7 @@
"punycode": { "punycode": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
"dev": true
} }
} }
}, },
@ -11263,11 +11306,19 @@
} }
}, },
"vue": { "vue": {
"version": "2.5.17", "version": "2.5.21",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.21.tgz",
"integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==", "integrity": "sha512-Aejvyyfhn0zjVeLvXd70h4hrE4zZDx1wfZqia6ekkobLmUZ+vNFQer53B4fu0EjWBSiqApxPejzkO1Znt3joxQ==",
"dev": true "dev": true
}, },
"vue-content-loader": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/vue-content-loader/-/vue-content-loader-0.2.1.tgz",
"integrity": "sha1-DrMy4qcmQ9V/sgnXLWUmVzsZH1o=",
"requires": {
"babel-helper-vue-jsx-merge-props": "^2.0.3"
}
},
"vue-functional-data-merge": { "vue-functional-data-merge": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-2.0.7.tgz", "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-2.0.7.tgz",
@ -11347,9 +11398,9 @@
} }
}, },
"vue-loading-overlay": { "vue-loading-overlay": {
"version": "3.1.0", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/vue-loading-overlay/-/vue-loading-overlay-3.1.0.tgz", "resolved": "https://registry.npmjs.org/vue-loading-overlay/-/vue-loading-overlay-3.1.1.tgz",
"integrity": "sha512-EJOaqxfkSwt6LRoKYnWWPch6fLRRzHWFxLBnRHjXHIK/fP0MSmbBLh9ZRpxarXJeDBiyykQevDXa7h7809JaAA==" "integrity": "sha512-6Iv0V/S++/LDRR3bgIZDJwBTgMVupuj+hjDb2YzTrEXbSEygtD10eJwZdMnEenLcD3ZAFz5D30qkNUYow9W2kw=="
}, },
"vue-style-loader": { "vue-style-loader": {
"version": "3.1.2", "version": "3.1.2",
@ -11362,9 +11413,9 @@
} }
}, },
"vue-template-compiler": { "vue-template-compiler": {
"version": "2.5.17", "version": "2.5.21",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.21.tgz",
"integrity": "sha512-63uI4syCwtGR5IJvZM0LN5tVsahrelomHtCxvRkZPJ/Tf3ADm1U1wG6KWycK3qCfqR+ygM5vewUvmJ0REAYksg==", "integrity": "sha512-Vmk5Cv7UcmI99B9nXJEkaK262IQNnHp5rJYo+EwYpe2epTAXqcVyExhV6pk8jTkxQK2vRc8v8KmZBAwdmUZvvw==",
"dev": true, "dev": true,
"requires": { "requires": {
"de-indent": "^1.0.2", "de-indent": "^1.0.2",
@ -11747,13 +11798,11 @@
"dev": true "dev": true
}, },
"ws": { "ws": {
"version": "3.3.3", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==",
"requires": { "requires": {
"async-limiter": "~1.0.0", "async-limiter": "~1.0.0"
"safe-buffer": "~5.1.0",
"ultron": "~1.1.0"
} }
}, },
"xmlhttprequest": { "xmlhttprequest": {

View File

@ -12,29 +12,32 @@
}, },
"devDependencies": { "devDependencies": {
"axios": "^0.18", "axios": "^0.18",
"bootstrap": "^4.1.3", "bootstrap": "^4.2.1",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"jquery": "^3.2", "jquery": "^3.2",
"laravel-mix": "^2.1.14", "laravel-mix": "^2.1.14",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"popper.js": "^1.14.4", "popper.js": "^1.14.6",
"vue": "^2.5.17" "vue": "^2.5.21",
"vue-template-compiler": "^2.5.21"
}, },
"dependencies": { "dependencies": {
"bootstrap-vue": "^2.0.0-rc.11", "bootstrap-vue": "^2.0.0-rc.11",
"emoji-mart-vue": "^2.6.6",
"filesize": "^3.6.1", "filesize": "^3.6.1",
"infinite-scroll": "^3.0.4", "infinite-scroll": "^3.0.4",
"laravel-echo": "^1.4.0", "laravel-echo": "^1.5.2",
"opencollective": "^1.0.3", "opencollective": "^1.0.3",
"opencollective-postinstall": "^2.0.1", "opencollective-postinstall": "^2.0.1",
"plyr": "^3.4.7", "plyr": "^3.4.7",
"pusher-js": "^4.2.2", "pusher-js": "^4.2.2",
"readmore-js": "^2.2.1", "readmore-js": "^2.2.1",
"socket.io-client": "^2.1.1", "socket.io-client": "^2.2.0",
"sweetalert": "^2.1.0", "sweetalert": "^2.1.2",
"twitter-text": "^2.0.5", "twitter-text": "^2.0.5",
"vue-content-loader": "^0.2.1",
"vue-infinite-loading": "^2.4.3", "vue-infinite-loading": "^2.4.3",
"vue-loading-overlay": "^3.1.0", "vue-loading-overlay": "^3.1.1",
"vue-timeago": "^5.0.0" "vue-timeago": "^5.0.0"
}, },
"collective": { "collective": {

4
public/css/app.css vendored

File diff suppressed because one or more lines are too long

2
public/js/app.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{ {
"/js/components.js": "/js/components.js?id=8998b5c828642646b512", "/js/components.js": "/js/components.js?id=29cbe1102d14e648aea7",
"/js/app.js": "/js/app.js?id=763d01bb175be69c8ad3", "/js/app.js": "/js/app.js?id=4721785cceb8eacd55f1",
"/css/app.css": "/css/app.css?id=986cee6cfca852babf8e", "/css/app.css": "/css/app.css?id=c477745c80d3370e7b29",
"/js/timeline.js": "/js/timeline.js?id=415bfde862ab8c5b4548", "/js/timeline.js": "/js/timeline.js?id=415bfde862ab8c5b4548",
"/js/activity.js": "/js/activity.js?id=723dfb98bbbc96a9d39f" "/js/activity.js": "/js/activity.js?id=723dfb98bbbc96a9d39f"
} }

View File

@ -2,7 +2,7 @@ window.Vue = require('vue');
import BootstrapVue from 'bootstrap-vue' import BootstrapVue from 'bootstrap-vue'
import InfiniteLoading from 'vue-infinite-loading'; import InfiniteLoading from 'vue-infinite-loading';
import Loading from 'vue-loading-overlay'; import Loading from 'vue-loading-overlay';
import VueTimeago from 'vue-timeago' import VueTimeago from 'vue-timeago';
Vue.use(BootstrapVue); Vue.use(BootstrapVue);
Vue.use(InfiniteLoading); Vue.use(InfiniteLoading);
@ -36,8 +36,8 @@ require('./components/commentform');
require('./components/searchform'); require('./components/searchform');
require('./components/bookmarkform'); require('./components/bookmarkform');
require('./components/statusform'); require('./components/statusform');
require('./components/embed'); //require('./components/embed');
require('./components/notifications'); //require('./components/notifications');
// import Echo from "laravel-echo" // import Echo from "laravel-echo"
@ -78,12 +78,16 @@ Vue.component(
require('./components/presenter/VideoAlbumPresenter.vue') require('./components/presenter/VideoAlbumPresenter.vue')
); );
Vue.component( Vue.component(
'mixed-album-presenter', 'mixed-album-presenter',
require('./components/presenter/MixedAlbumPresenter.vue') require('./components/presenter/MixedAlbumPresenter.vue')
); );
// Vue.component(
// 'micro',
// require('./components/Micro.vue')
// );
Vue.component( Vue.component(
'follow-suggestions', 'follow-suggestions',
require('./components/FollowSuggestions.vue') require('./components/FollowSuggestions.vue')
@ -114,11 +118,6 @@ Vue.component(
require('./components/Timeline.vue') require('./components/Timeline.vue')
); );
// Vue.component(
// 'micro',
// require('./components/Micro.vue')
// );
Vue.component( Vue.component(
'passport-clients', 'passport-clients',
require('./components/passport/Clients.vue') require('./components/passport/Clients.vue')

View File

@ -3,7 +3,9 @@
<div class="row"> <div class="row">
<div class="col-md-8 col-lg-8 pt-2 px-0 my-3 timeline order-2 order-md-1"> <div class="col-md-8 col-lg-8 pt-2 px-0 my-3 timeline order-2 order-md-1">
<div class="loader text-center"> <div class="loader text-center">
<div class="lds-ring"><div></div><div></div><div></div><div></div></div> <div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> </div>
<div class="card mb-4 status-card card-md-rounded-0" :data-status-id="status.id" v-for="(status, index) in feed" :key="status.id"> <div class="card mb-4 status-card card-md-rounded-0" :data-status-id="status.id" v-for="(status, index) in feed" :key="status.id">
@ -101,7 +103,9 @@
<div class="mb-4"> <div class="mb-4">
<div class="card profile-card"> <div class="card profile-card">
<div class="card-body loader text-center"> <div class="card-body loader text-center">
<div class="lds-ring"><div></div><div></div><div></div><div></div></div> <div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> </div>
<div class="card-body contents d-none"> <div class="card-body contents d-none">
<div class="media d-flex align-items-center"> <div class="media d-flex align-items-center">
@ -142,7 +146,9 @@
</p> </p>
</div> </div>
<div class="card-body loader text-center" style="height: 300px;"> <div class="card-body loader text-center" style="height: 300px;">
<div class="lds-ring"><div></div><div></div><div></div><div></div></div> <div class="spinner-border" role="status">
<span class="sr-only">Loading...</span>
</div>
</div> </div>
<div class="card-body pt-2 contents" style="max-height: 300px; overflow-y: scroll;"> <div class="card-body pt-2 contents" style="max-height: 300px; overflow-y: scroll;">
<div class="media mb-3 align-items-center" v-for="(n, index) in notifications"> <div class="media mb-3 align-items-center" v-for="(n, index) in notifications">

View File

@ -9,4 +9,7 @@ return [
'privateProfileWarning' => 'This Account is Private', 'privateProfileWarning' => 'This Account is Private',
'alreadyFollow' => 'Already follow :username?', 'alreadyFollow' => 'Already follow :username?',
'loginToSeeProfile' => 'to see their photos and videos.', 'loginToSeeProfile' => 'to see their photos and videos.',
'status.disabled.header' => 'Profile Unavailable',
'status.disabled.body' => 'Sorry, this profile is not available at the moment. Please try again shortly.',
]; ];

View File

@ -0,0 +1,18 @@
@extends('layouts.app',['title' => "Account Temporarily Unavailable"])
@section('content')
<div class="container">
<div class="profile-timeline mt-2 mt-md-4">
<div class="alert alert-danger">
<div class="py-2">
<p class="lead font-weight-bold mb-0">
{{__('profile.status.disabled.header')}}
</p>
<p class="mb-0">
{{__('profile.status.disabled.body')}}
</p>
</div>
</div>
</div>
</div>
@endsection

View File

@ -82,8 +82,9 @@
</div> </div>
<hr> <hr>
<div class="form-group row"> <div class="form-group row">
<div class="col-12 text-right"> <div class="col-12 d-flex align-items-center justify-content-between">
<button type="submit" class="btn btn-primary font-weight-bold">Submit</button> <a class="font-weight-bold" href="{{route('settings.remove.temporary')}}">Temporarily Disable Account</a>
<button type="submit" class="btn btn-primary font-weight-bold float-right">Submit</button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -22,7 +22,7 @@
<p> <p>
<form method="post"> <form method="post">
@csrf @csrf
<div class="custom-control custom-checkbox mb-3"> <div class="custom-control custom-switch mb-3">
<input type="checkbox" class="custom-control-input" id="confirm-check"> <input type="checkbox" class="custom-control-input" id="confirm-check">
<label class="custom-control-label font-weight-bold" for="confirm-check">I confirm that this action is not reversible, and will result in the permanent deletion of my account.</label> <label class="custom-control-label font-weight-bold" for="confirm-check">I confirm that this action is not reversible, and will result in the permanent deletion of my account.</label>
</div> </div>

View File

@ -0,0 +1,30 @@
@extends('settings.template')
@section('section')
<div class="title">
<h3 class="font-weight-bold">Temporarily Disable Your Account</h3>
</div>
<hr>
<div class="mt-3">
<p>Hi <span class="font-weight-bold">{{Auth::user()->username}}</span>,</p>
<p>You can disable your account instead of deleting it. This means your account will be hidden until you reactivate it by logging back in.</p>
<p class="pb-1">You can only disable your account once a week.</p>
<p class="font-weight-bold">Keeping Your Data Safe</p>
<p class="pb-3">Nothing is more important to us than the safety and security of this community. People put their trust in us by sharing moments of their lives on Pixelfed. So we will never make any compromises when it comes to safeguarding your data.</p>
<p class="pb-2">When you press the button below, your photos, comments and likes will be hidden until you reactivate your account by logging back in.</p>
<p>
<form method="post">
@csrf
<button type="submit" class="btn btn-primary font-weight-bold py-0">Temporarily Disable Account</button>
</form>
</p>
</div>
@endsection

View File

@ -12,3 +12,5 @@ use Illuminate\Http\Request;
| is assigned the "api" middleware group. Enjoy building your API! | is assigned the "api" middleware group. Enjoy building your API!
| |
*/ */
Route::post('/users/{username}/inbox', 'FederationController@userInbox');

View File

@ -76,6 +76,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::post('follow', 'FollowerController@store')->middleware('throttle:250,1440'); Route::post('follow', 'FollowerController@store')->middleware('throttle:250,1440');
Route::post('bookmark', 'BookmarkController@store')->middleware('throttle:250,1440'); Route::post('bookmark', 'BookmarkController@store')->middleware('throttle:250,1440');
Route::get('lang/{locale}', 'SiteController@changeLocale'); Route::get('lang/{locale}', 'SiteController@changeLocale');
Route::get('restored', 'AccountController@accountRestored');
Route::get('verify-email', 'AccountController@verifyEmail'); Route::get('verify-email', 'AccountController@verifyEmail');
Route::post('verify-email', 'AccountController@sendVerifyEmail')->middleware('throttle:10,1440'); Route::post('verify-email', 'AccountController@sendVerifyEmail')->middleware('throttle:10,1440');
@ -133,12 +134,12 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('privacy/blocked-instances', 'SettingsController@blockedInstances')->name('settings.privacy.blocked-instances'); Route::get('privacy/blocked-instances', 'SettingsController@blockedInstances')->name('settings.privacy.blocked-instances');
// Todo: Release in 0.7.2 // Todo: Release in 0.7.2
// Route::group(['prefix' => 'remove', 'middleware' => 'dangerzone'], function() { Route::group(['prefix' => 'remove', 'middleware' => 'dangerzone'], function() {
// Route::get('request/temporary', 'SettingsController@removeAccountTemporary')->name('settings.remove.temporary'); Route::get('request/temporary', 'SettingsController@removeAccountTemporary')->name('settings.remove.temporary');
// Route::post('request/temporary', 'SettingsController@removeAccountTemporarySubmit'); Route::post('request/temporary', 'SettingsController@removeAccountTemporarySubmit');
// Route::get('request/permanent', 'SettingsController@removeAccountPermanent')->name('settings.remove.permanent'); Route::get('request/permanent', 'SettingsController@removeAccountPermanent')->name('settings.remove.permanent');
// Route::post('request/permanent', 'SettingsController@removeAccountPermanentSubmit'); Route::post('request/permanent', 'SettingsController@removeAccountPermanentSubmit');
// }); });
Route::group(['prefix' => 'security', 'middleware' => 'dangerzone'], function() { Route::group(['prefix' => 'security', 'middleware' => 'dangerzone'], function() {
Route::get( Route::get(