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

View File

@ -37,7 +37,7 @@ class FollowerController extends Controller
protected function handleFollowRequest($item)
{
$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;
$blocked = UserFilter::whereUserId($target->id)
->whereFilterType('block')

View File

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

View File

@ -20,7 +20,11 @@ class ProfileController extends Controller
public function show(Request $request, $username)
{
$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
@ -30,7 +34,11 @@ class ProfileController extends Controller
$loggedIn = Auth::check();
$isPrivate = false;
$isBlocked = false;
if($user->status != null) {
return ProfileController::accountCheck($user);
}
if ($user->remote_url) {
$settings = new \StdClass;
$settings->crawlable = false;
@ -118,8 +126,27 @@ class ProfileController extends Controller
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)
{
if($user->status != null) {
return ProfileController::accountCheck($user);
}
$fractal = new Fractal\Manager();
$resource = new Fractal\Resource\Item($user, new ProfileTransformer);
$res = $fractal->createData($resource)->toArray();
@ -129,6 +156,9 @@ class ProfileController extends Controller
public function showAtomFeed(Request $request, $user)
{
$profile = $user = Profile::whereUsername($user)->firstOrFail();
if($profile->status != null) {
return $this->accountCheck($profile);
}
if($profile->is_private || Auth::check()) {
$blocked = $this->blockedProfileCheck($profile);
$check = $this->privateProfileCheck($profile, null);
@ -144,7 +174,9 @@ class ProfileController extends Controller
public function followers(Request $request, $username)
{
$profile = $user = Profile::whereUsername($username)->firstOrFail();
if($profile->status != null) {
return $this->accountCheck($profile);
}
// TODO: fix $profile/$user mismatch in profile & follower templates
$owner = Auth::check() && Auth::id() === $user->user_id;
$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'));
}
}
$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;
if ($user->remote_url) {
$settings = new \StdClass;
@ -172,6 +204,9 @@ class ProfileController extends Controller
public function following(Request $request, $username)
{
$profile = $user = Profile::whereUsername($username)->firstOrFail();
if($profile->status != null) {
return $this->accountCheck($profile);
}
// TODO: fix $profile/$user mismatch in profile & follower templates
$owner = Auth::check() && Auth::id() === $user->user_id;
$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'));
}
}
$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;
if ($user->remote_url) {
$settings = new \StdClass;
@ -201,7 +236,10 @@ class ProfileController extends Controller
if (Auth::check() === false || $username !== Auth::user()->username) {
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;
$owner = true;
$following = false;

View File

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

View File

@ -22,7 +22,7 @@ class SearchController extends Controller
return;
}
$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([]);
$hashtags = Hashtag::select('id', 'name', 'slug')->where('slug', 'like', '%'.$tag.'%')->limit(20)->get();
if($hashtags->count() > 0) {
@ -39,6 +39,7 @@ class SearchController extends Controller
$tokens->push($tags);
}
$users = Profile::select('username', 'name', 'id')
->whereNull('status')
->where('username', 'like', '%'.$tag.'%')
->limit(20)
->get();

View File

@ -5,10 +5,8 @@ namespace App\Http\Controllers;
use App\AccountLog;
use App\Following;
use App\UserFilter;
use Auth;
use DB;
use Cache;
use Purify;
use Auth, DB, Cache, Purify;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Settings\{
HomeSettings,
@ -137,6 +135,18 @@ class SettingsController extends Controller
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)
{
return view('settings.remove.permanent');
@ -148,7 +158,14 @@ class SettingsController extends Controller
if($user->is_admin == true) {
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();
return redirect('/');
}

View File

@ -21,10 +21,22 @@ class StatusController extends Controller
{
$user = Profile::whereUsername($username)->firstOrFail();
if($user->status != null) {
return ProfileController::accountCheck($user);
}
$status = Status::whereProfileId($user->id)
->whereNotIn('visibility',['draft','direct'])
->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(!Auth::check()) {
abort(403);

View File

@ -37,11 +37,9 @@ class NewStatusPipeline implements ShouldQueue
$status = $this->status;
StatusEntityLexer::dispatch($status);
StatusActivityPubDeliver::dispatch($status);
Cache::forever('post.'.$status->id, $status);
$redis = Redis::connection();
$redis->lpush(config('cache.prefix').':user.'.$status->profile_id.'.posts', $status->id);
// Cache::forever('post.'.$status->id, $status);
// $redis = Redis::connection();
// $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;
if($status->local == true || $status->url || $status->uri) {
return;
}
$audience = $status->profile->getAudienceInbox();
$profile = $status->profile;
@ -49,7 +53,5 @@ class StatusActivityPubDeliver implements ShouldQueue
foreach($audience as $url) {
Helpers::sendSignedObject($profile, $url, $activity);
}
// todo: fanout on write
}
}

View File

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

View File

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

View File

@ -32,7 +32,7 @@ class Inbox
public function handle()
{
$this->authenticatePayload();
$this->handleVerb();
}
public function authenticatePayload()
@ -142,16 +142,11 @@ class Inbox
$activity = $this->payload['object'];
$actor = $this->actorFirstOrCreate($this->payload['actor']);
$inReplyTo = $activity['inReplyTo'];
$url = $activity['id'];
if(!Helpers::statusFirstOrFetch($activity['url'], true)) {
$this->logger->delete();
if(!Helpers::statusFirstOrFetch($url, true)) {
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()
@ -164,12 +159,11 @@ class Inbox
if(Helpers::userInAudience($this->profile, $this->payload) == false) {
//Log::error('AP:inbox:userInAudience:false - Activity#'.$this->logger->id);
$logger = Activity::find($this->logger->id);
$logger->delete();
return;
}
if(Status::whereUrl($activity['url'])->exists()) {
$url = $activity['id'];
if(Status::whereUrl($url)->exists()) {
return;
}
@ -178,18 +172,12 @@ class Inbox
$status->profile_id = $actor->id;
$status->caption = strip_tags($activity['content']);
$status->visibility = $status->scope = 'public';
$status->url = $activity['url'];
$status->url = $url;
$status->save();
return $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()
@ -214,7 +202,6 @@ class Inbox
'local_profile' => empty($actor->domain)
]);
if($follower->wasRecentlyCreated == false) {
$this->logger->delete();
return;
}
// send notification
@ -228,37 +215,53 @@ class Inbox
$notification->item_type = "App\Profile";
$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
$accept = [
'@context' => 'https://www.w3.org/ns/activitystreams',
'id' => $follower->permalink('/accept'),
'id' => $target->permalink().'#accepts/follows/',
'type' => 'Accept',
'actor' => $target->permalink(),
'object' => [
'id' => $this->payload['id'],
'id' => $actor->permalink('#follows/'.$target->id),
'type' => 'Follow',
'actor' => $target->permalink(),
'object' => $actor->permalink()
'actor' => $actor->permalink(),
'object' => $target->permalink()
]
];
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()
{
$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()
@ -268,7 +271,19 @@ class Inbox
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()
@ -289,10 +304,6 @@ class Inbox
return;
}
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'];
$profile = self::actorFirstOrCreate($actor);
$obj = $this->payload['object'];
$status = Helpers::statusFirstOrFetch($obj['object']);
switch ($obj['type']) {
case 'Like':
$status = Helpers::statusFirstOrFetch($obj['object']);
Like::whereProfileId($profile->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;
}
$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"
}
},
"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": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
"dev": true
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
},
"align-text": {
"version": "0.1.4",
@ -164,7 +168,6 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
@ -199,7 +202,6 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "~1.0.2"
}
@ -632,6 +634,11 @@
"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": {
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
@ -1243,8 +1250,7 @@
"big.js": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
"dev": true
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
},
"binary-extensions": {
"version": "1.11.0",
@ -1253,9 +1259,9 @@
"dev": true
},
"blob": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE="
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
},
"block-stream": {
"version": "0.0.9",
@ -1328,9 +1334,9 @@
}
},
"bootstrap": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz",
"integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w=="
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.2.1.tgz",
"integrity": "sha512-tt/7vIv3Gm2mnd/WeDx36nfGGHleil0Wg8IeB7eMrVkY0fZ5iTaBisSh8oNANc2IBsCc6vCgCNTIM/IEN0+50Q=="
},
"bootstrap-vue": {
"version": "2.0.0-rc.11",
@ -1651,7 +1657,6 @@
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@ -1884,7 +1889,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
@ -1892,8 +1896,7 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "0.3.0",
@ -2123,7 +2126,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
"integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
"dev": true,
"requires": {
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
@ -2134,14 +2136,12 @@
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"js-yaml": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@ -2151,7 +2151,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"dev": true,
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
@ -2842,11 +2841,72 @@
"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": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
"dev": true
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
},
"encodeurl": {
"version": "1.0.2",
@ -2872,9 +2932,9 @@
}
},
"engine.io-client": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
"integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.1.tgz",
"integrity": "sha512-q66JBFuQcy7CSlfAz9L3jH+v7DTT3i6ZEadYcVj2pOs8/0uJHLxKX3WBkGTvULJMdz0tUCyJag0aKT/dpXL9BQ==",
"requires": {
"component-emitter": "1.2.1",
"component-inherit": "0.0.3",
@ -2884,20 +2944,20 @@
"indexof": "0.0.1",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"ws": "~3.3.1",
"ws": "~6.1.0",
"xmlhttprequest-ssl": "~1.5.4",
"yeast": "0.1.2"
}
},
"engine.io-parser": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz",
"integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==",
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
"integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
"requires": {
"after": "0.8.2",
"arraybuffer.slice": "~0.0.7",
"base64-arraybuffer": "0.1.5",
"blob": "0.0.4",
"blob": "0.0.5",
"has-binary2": "~1.0.2"
}
},
@ -2926,7 +2986,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
"requires": {
"is-arrayish": "^0.2.1"
}
@ -3458,8 +3517,7 @@
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
"dev": true
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"fastparse": {
"version": "1.1.1",
@ -4563,8 +4621,7 @@
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"has-unicode": {
"version": "2.0.1",
@ -4945,7 +5002,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
"integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
"dev": true,
"requires": {
"import-from": "^2.1.0"
}
@ -4954,7 +5010,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
"integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
"dev": true,
"requires": {
"resolve-from": "^3.0.0"
}
@ -5141,8 +5196,7 @@
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-binary-path": {
"version": "1.0.1",
@ -5222,8 +5276,7 @@
"is-directory": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
"dev": true
"integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
},
"is-dotfile": {
"version": "1.0.3",
@ -5477,8 +5530,7 @@
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
"dev": true
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"json-schema": {
"version": "0.2.3",
@ -5507,8 +5559,7 @@
"json5": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
},
"jsonfile": {
"version": "3.0.1",
@ -5544,9 +5595,9 @@
"dev": true
},
"laravel-echo": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.4.0.tgz",
"integrity": "sha512-O0vkToCCpxuH9dYAlugTLQzG0BmxvGrjXim0LHZ0VPsFu/Y+sXnV9GvYbmcBq1rcJymQc/6GHMUCDY01lN26lQ=="
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.5.2.tgz",
"integrity": "sha512-Xw9QsxJKapv0C2UTnXRRIM1+epL3+qaSRGd7V8pXEuIHnxjcdpk2I7YLauDzYhBNMKEKWtlE/sv9Wgs+hYKnbg=="
},
"laravel-mix": {
"version": "2.1.14",
@ -5638,7 +5689,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
"dev": true,
"requires": {
"big.js": "^3.1.3",
"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": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
@ -6964,9 +7019,9 @@
}
},
"popper.js": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz",
"integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY="
"version": "1.14.6",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.6.tgz",
"integrity": "sha512-AGwHGQBKumlk/MDfrSOf0JHhJCImdDMcGNoqKmKkU+68GFazv3CQ6q9r7Ja1sKDZmYWTckY/uLyEznheTDycnA=="
},
"portfinder": {
"version": "1.0.17",
@ -7662,7 +7717,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
"integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==",
"dev": true,
"requires": {
"cosmiconfig": "^4.0.0",
"import-cwd": "^2.0.0"
@ -9591,8 +9645,7 @@
"require-from-string": {
"version": "2.0.2",
"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==",
"dev": true
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
},
"require-main-filename": {
"version": "1.0.1",
@ -9627,8 +9680,7 @@
"resolve-from": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
"dev": true
"integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
},
"resolve-url": {
"version": "0.2.1",
@ -9759,7 +9811,8 @@
"safe-buffer": {
"version": "5.1.2",
"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": {
"version": "1.1.0",
@ -10208,30 +10261,30 @@
}
},
"socket.io-client": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
"integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz",
"integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==",
"requires": {
"backo2": "1.0.2",
"base64-arraybuffer": "0.1.5",
"component-bind": "1.0.0",
"component-emitter": "1.2.1",
"debug": "~3.1.0",
"engine.io-client": "~3.2.0",
"engine.io-client": "~3.3.1",
"has-binary2": "~1.0.2",
"has-cors": "1.1.0",
"indexof": "0.0.1",
"object-component": "0.0.3",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"socket.io-parser": "~3.2.0",
"socket.io-parser": "~3.3.0",
"to-array": "0.1.4"
}
},
"socket.io-parser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
"integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz",
"integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==",
"requires": {
"component-emitter": "1.2.1",
"debug": "~3.1.0",
@ -10307,8 +10360,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-resolve": {
"version": "0.5.2",
@ -10441,8 +10493,7 @@
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"sshpk": {
"version": "1.14.2",
@ -10636,7 +10687,6 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
@ -10657,9 +10707,9 @@
}
},
"sweetalert": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.0.tgz",
"integrity": "sha512-9YKj0SvjKyBfRWco50UOsIbXVeifYbxzT9Qda7EsqC01eafHGCSG0IR7g942ufjzt7lnwO8ZZBwr6emXv2fQrg==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/sweetalert/-/sweetalert-2.1.2.tgz",
"integrity": "sha512-iWx7X4anRBNDa/a+AdTmvAzQtkN1+s4j/JJRWlHpYE8Qimkohs8/XnFcWeYHH2lMA8LRCa5tj2d244If3S/hzA==",
"requires": {
"es6-object-assign": "^1.1.0",
"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": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
@ -11127,7 +11172,6 @@
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
},
@ -11135,8 +11179,7 @@
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
}
}
},
@ -11263,11 +11306,19 @@
}
},
"vue": {
"version": "2.5.17",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz",
"integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==",
"version": "2.5.21",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.5.21.tgz",
"integrity": "sha512-Aejvyyfhn0zjVeLvXd70h4hrE4zZDx1wfZqia6ekkobLmUZ+vNFQer53B4fu0EjWBSiqApxPejzkO1Znt3joxQ==",
"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": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-2.0.7.tgz",
@ -11347,9 +11398,9 @@
}
},
"vue-loading-overlay": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/vue-loading-overlay/-/vue-loading-overlay-3.1.0.tgz",
"integrity": "sha512-EJOaqxfkSwt6LRoKYnWWPch6fLRRzHWFxLBnRHjXHIK/fP0MSmbBLh9ZRpxarXJeDBiyykQevDXa7h7809JaAA=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/vue-loading-overlay/-/vue-loading-overlay-3.1.1.tgz",
"integrity": "sha512-6Iv0V/S++/LDRR3bgIZDJwBTgMVupuj+hjDb2YzTrEXbSEygtD10eJwZdMnEenLcD3ZAFz5D30qkNUYow9W2kw=="
},
"vue-style-loader": {
"version": "3.1.2",
@ -11362,9 +11413,9 @@
}
},
"vue-template-compiler": {
"version": "2.5.17",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz",
"integrity": "sha512-63uI4syCwtGR5IJvZM0LN5tVsahrelomHtCxvRkZPJ/Tf3ADm1U1wG6KWycK3qCfqR+ygM5vewUvmJ0REAYksg==",
"version": "2.5.21",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.21.tgz",
"integrity": "sha512-Vmk5Cv7UcmI99B9nXJEkaK262IQNnHp5rJYo+EwYpe2epTAXqcVyExhV6pk8jTkxQK2vRc8v8KmZBAwdmUZvvw==",
"dev": true,
"requires": {
"de-indent": "^1.0.2",
@ -11747,13 +11798,11 @@
"dev": true
},
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz",
"integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==",
"requires": {
"async-limiter": "~1.0.0",
"safe-buffer": "~5.1.0",
"ultron": "~1.1.0"
"async-limiter": "~1.0.0"
}
},
"xmlhttprequest": {

View File

@ -12,29 +12,32 @@
},
"devDependencies": {
"axios": "^0.18",
"bootstrap": "^4.1.3",
"bootstrap": "^4.2.1",
"cross-env": "^5.2.0",
"jquery": "^3.2",
"laravel-mix": "^2.1.14",
"lodash": "^4.17.11",
"popper.js": "^1.14.4",
"vue": "^2.5.17"
"popper.js": "^1.14.6",
"vue": "^2.5.21",
"vue-template-compiler": "^2.5.21"
},
"dependencies": {
"bootstrap-vue": "^2.0.0-rc.11",
"emoji-mart-vue": "^2.6.6",
"filesize": "^3.6.1",
"infinite-scroll": "^3.0.4",
"laravel-echo": "^1.4.0",
"laravel-echo": "^1.5.2",
"opencollective": "^1.0.3",
"opencollective-postinstall": "^2.0.1",
"plyr": "^3.4.7",
"pusher-js": "^4.2.2",
"readmore-js": "^2.2.1",
"socket.io-client": "^2.1.1",
"sweetalert": "^2.1.0",
"socket.io-client": "^2.2.0",
"sweetalert": "^2.1.2",
"twitter-text": "^2.0.5",
"vue-content-loader": "^0.2.1",
"vue-infinite-loading": "^2.4.3",
"vue-loading-overlay": "^3.1.0",
"vue-loading-overlay": "^3.1.1",
"vue-timeago": "^5.0.0"
},
"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/app.js": "/js/app.js?id=763d01bb175be69c8ad3",
"/css/app.css": "/css/app.css?id=986cee6cfca852babf8e",
"/js/components.js": "/js/components.js?id=29cbe1102d14e648aea7",
"/js/app.js": "/js/app.js?id=4721785cceb8eacd55f1",
"/css/app.css": "/css/app.css?id=c477745c80d3370e7b29",
"/js/timeline.js": "/js/timeline.js?id=415bfde862ab8c5b4548",
"/js/activity.js": "/js/activity.js?id=723dfb98bbbc96a9d39f"
}

View File

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

View File

@ -3,7 +3,9 @@
<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="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 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="card profile-card">
<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 class="card-body contents d-none">
<div class="media d-flex align-items-center">
@ -142,7 +146,9 @@
</p>
</div>
<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 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">

View File

@ -9,4 +9,7 @@ return [
'privateProfileWarning' => 'This Account is Private',
'alreadyFollow' => 'Already follow :username?',
'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>
<hr>
<div class="form-group row">
<div class="col-12 text-right">
<button type="submit" class="btn btn-primary font-weight-bold">Submit</button>
<div class="col-12 d-flex align-items-center justify-content-between">
<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>
</form>

View File

@ -22,7 +22,7 @@
<p>
<form method="post">
@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">
<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>

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!
|
*/
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('bookmark', 'BookmarkController@store')->middleware('throttle:250,1440');
Route::get('lang/{locale}', 'SiteController@changeLocale');
Route::get('restored', 'AccountController@accountRestored');
Route::get('verify-email', 'AccountController@verifyEmail');
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');
// Todo: Release in 0.7.2
// Route::group(['prefix' => 'remove', 'middleware' => 'dangerzone'], function() {
// Route::get('request/temporary', 'SettingsController@removeAccountTemporary')->name('settings.remove.temporary');
// Route::post('request/temporary', 'SettingsController@removeAccountTemporarySubmit');
// Route::get('request/permanent', 'SettingsController@removeAccountPermanent')->name('settings.remove.permanent');
// Route::post('request/permanent', 'SettingsController@removeAccountPermanentSubmit');
// });
Route::group(['prefix' => 'remove', 'middleware' => 'dangerzone'], function() {
Route::get('request/temporary', 'SettingsController@removeAccountTemporary')->name('settings.remove.temporary');
Route::post('request/temporary', 'SettingsController@removeAccountTemporarySubmit');
Route::get('request/permanent', 'SettingsController@removeAccountPermanent')->name('settings.remove.permanent');
Route::post('request/permanent', 'SettingsController@removeAccountPermanentSubmit');
});
Route::group(['prefix' => 'security', 'middleware' => 'dangerzone'], function() {
Route::get(