mirror of
https://github.com/pixelfed/pixelfed.git
synced 2025-01-11 14:40:46 +00:00
fix merge conflict
This commit is contained in:
commit
a4929efe5c
33 changed files with 383 additions and 119 deletions
|
@ -53,3 +53,5 @@ MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||||
MIX_APP_URL="${APP_URL}"
|
MIX_APP_URL="${APP_URL}"
|
||||||
MIX_API_BASE="${API_BASE}"
|
MIX_API_BASE="${API_BASE}"
|
||||||
MIX_API_SEARCH="${API_SEARCH}"
|
MIX_API_SEARCH="${API_SEARCH}"
|
||||||
|
|
||||||
|
TELESCOPE_ENABLED=false
|
||||||
|
|
|
@ -17,7 +17,7 @@ there is a stable release**. The following setup instructions are intended for
|
||||||
testing and development.
|
testing and development.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- PHP >= 7.1.3 (7.2+ recommended for stable version)
|
- PHP >= 7.1.3 < 7.3 (7.2.x recommended for stable version)
|
||||||
- MySQL >= 5.7, Postgres (MariaDB and sqlite are not supported yet)
|
- MySQL >= 5.7, Postgres (MariaDB and sqlite are not supported yet)
|
||||||
- Redis
|
- Redis
|
||||||
- Composer
|
- Composer
|
||||||
|
|
|
@ -39,11 +39,6 @@ class FixUsernames extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
if(version_compare(config('pixelfed.version'), '0.7.2') !== -1) {
|
|
||||||
$this->info('This command is only for versions lower than 0.7.2');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->info('Collecting data ...');
|
$this->info('Collecting data ...');
|
||||||
|
|
||||||
$affected = collect([]);
|
$affected = collect([]);
|
||||||
|
|
|
@ -339,6 +339,11 @@ class AccountController extends Controller
|
||||||
$request->session()->push('2fa.session.active', true);
|
$request->session()->push('2fa.session.active', true);
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if($this->twoFactorBackupCheck($request, $code, $user)) {
|
||||||
|
return redirect('/');
|
||||||
|
}
|
||||||
|
|
||||||
if($request->session()->has('2fa.attempts')) {
|
if($request->session()->has('2fa.attempts')) {
|
||||||
$count = (int) $request->session()->has('2fa.attempts');
|
$count = (int) $request->session()->has('2fa.attempts');
|
||||||
$request->session()->push('2fa.attempts', $count + 1);
|
$request->session()->push('2fa.attempts', $count + 1);
|
||||||
|
@ -350,4 +355,31 @@ class AccountController extends Controller
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function twoFactorBackupCheck($request, $code, User $user)
|
||||||
|
{
|
||||||
|
$backupCodes = $user->{'2fa_backup_codes'};
|
||||||
|
if($backupCodes) {
|
||||||
|
$codes = json_decode($backupCodes, true);
|
||||||
|
foreach ($codes as $c) {
|
||||||
|
if(hash_equals($c, $code)) {
|
||||||
|
// remove code
|
||||||
|
$codes = array_flatten(array_diff($codes, [$code]));
|
||||||
|
$user->{'2fa_backup_codes'} = json_encode($codes);
|
||||||
|
$user->save();
|
||||||
|
$request->session()->push('2fa.session.active', true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function accountRestored(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,24 +181,75 @@ XML;
|
||||||
return ProfileController::accountCheck($profile);
|
return ProfileController::accountCheck($profile);
|
||||||
}
|
}
|
||||||
$body = $request->getContent();
|
$body = $request->getContent();
|
||||||
$bodyDecoded = json_decode($body, true);
|
$bodyDecoded = json_decode($body, true, 8);
|
||||||
|
if($this->verifySignature($request, $profile) == true) {
|
||||||
|
InboxWorker::dispatch($request->headers->all(), $profile, $bodyDecoded);
|
||||||
|
} else if($this->blindKeyRotation($request, $profile) == true) {
|
||||||
|
InboxWorker::dispatch($request->headers->all(), $profile, $bodyDecoded);
|
||||||
|
} else {
|
||||||
|
abort(400, 'Bad Signature');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function verifySignature(Request $request, Profile $profile)
|
||||||
|
{
|
||||||
|
$body = $request->getContent();
|
||||||
|
$bodyDecoded = json_decode($body, true, 8);
|
||||||
$signature = $request->header('signature');
|
$signature = $request->header('signature');
|
||||||
if(!$signature) {
|
if(!$signature) {
|
||||||
abort(400, 'Missing signature header');
|
abort(400, 'Missing signature header');
|
||||||
}
|
}
|
||||||
$signatureData = HttpSignature::parseSignatureHeader($signature);
|
$signatureData = HttpSignature::parseSignatureHeader($signature);
|
||||||
$actor = Profile::whereKeyId($signatureData['keyId'])->first();
|
$keyId = Helpers::validateUrl($signatureData['keyId']);
|
||||||
|
$id = Helpers::validateUrl($bodyDecoded['id']);
|
||||||
|
$keyDomain = parse_url($keyId, PHP_URL_HOST);
|
||||||
|
$idDomain = parse_url($id, PHP_URL_HOST);
|
||||||
|
if(isset($bodyDecoded['object'])
|
||||||
|
&& is_array($bodyDecoded['object'])
|
||||||
|
&& isset($bodyDecoded['object']['attributedTo'])
|
||||||
|
) {
|
||||||
|
if(parse_url($bodyDecoded['object']['attributedTo'], PHP_URL_HOST) !== $keyDomain) {
|
||||||
|
abort(400, 'Invalid request');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!$keyDomain || !$idDomain || $keyDomain !== $idDomain) {
|
||||||
|
abort(400, 'Invalid request');
|
||||||
|
}
|
||||||
|
$actor = Profile::whereKeyId($keyId)->first();
|
||||||
if(!$actor) {
|
if(!$actor) {
|
||||||
$actor = Helpers::profileFirstOrNew($bodyDecoded['actor']);
|
$actor = Helpers::profileFirstOrNew($bodyDecoded['actor']);
|
||||||
}
|
}
|
||||||
$pkey = openssl_pkey_get_public($actor->public_key);
|
$pkey = openssl_pkey_get_public($actor->public_key);
|
||||||
$inboxPath = "/users/{$profile->username}/inbox";
|
$inboxPath = "/users/{$profile->username}/inbox";
|
||||||
list($verified, $headers) = HTTPSignature::verify($pkey, $signatureData, $request->headers->all(), $inboxPath, $body);
|
list($verified, $headers) = HTTPSignature::verify($pkey, $signatureData, $request->headers->all(), $inboxPath, $body);
|
||||||
if($verified !== 1) {
|
if($verified == 1) {
|
||||||
abort(400, 'Invalid signature.');
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
InboxWorker::dispatch($request->headers->all(), $profile, $bodyDecoded);
|
}
|
||||||
return;
|
|
||||||
|
protected function blindKeyRotation(Request $request, Profile $profile)
|
||||||
|
{
|
||||||
|
$signature = $request->header('signature');
|
||||||
|
if(!$signature) {
|
||||||
|
abort(400, 'Missing signature header');
|
||||||
|
}
|
||||||
|
$signatureData = HttpSignature::parseSignatureHeader($signature);
|
||||||
|
$keyId = Helpers::validateUrl($signatureData['keyId']);
|
||||||
|
$actor = Profile::whereKeyId($keyId)->first();
|
||||||
|
$res = Zttp::timeout(5)->withHeaders([
|
||||||
|
'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||||
|
'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org',
|
||||||
|
])->get($actor->remote_url);
|
||||||
|
$res = json_decode($res->body(), true, 8);
|
||||||
|
if($res['publicKey']['id'] !== $actor->key_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$actor->public_key = $res['publicKey']['publicKeyPem'];
|
||||||
|
$actor->save();
|
||||||
|
return $this->verifySignature($request, $profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function userFollowing(Request $request, $username)
|
public function userFollowing(Request $request, $username)
|
||||||
|
|
|
@ -300,7 +300,7 @@ class PublicApiController extends Controller
|
||||||
->whereNotIn('profile_id', $filtered)
|
->whereNotIn('profile_id', $filtered)
|
||||||
->whereNull('in_reply_to_id')
|
->whereNull('in_reply_to_id')
|
||||||
->whereNull('reblog_of_id')
|
->whereNull('reblog_of_id')
|
||||||
->whereVisibility('public')
|
->whereIn('visibility',['public', 'unlisted', 'private'])
|
||||||
->withCount(['comments', 'likes'])
|
->withCount(['comments', 'likes'])
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
|
@ -311,7 +311,7 @@ class PublicApiController extends Controller
|
||||||
->whereNotIn('profile_id', $filtered)
|
->whereNotIn('profile_id', $filtered)
|
||||||
->whereNull('in_reply_to_id')
|
->whereNull('in_reply_to_id')
|
||||||
->whereNull('reblog_of_id')
|
->whereNull('reblog_of_id')
|
||||||
->whereVisibility('public')
|
->whereIn('visibility',['public', 'unlisted', 'private'])
|
||||||
->withCount(['comments', 'likes'])
|
->withCount(['comments', 'likes'])
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->simplePaginate($limit);
|
->simplePaginate($limit);
|
||||||
|
|
|
@ -110,6 +110,19 @@ trait SecuritySettings
|
||||||
return view('settings.security.2fa.recovery-codes', compact('user', 'codes'));
|
return view('settings.security.2fa.recovery-codes', compact('user', 'codes'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function securityTwoFactorRecoveryCodesRegenerate(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if(!$user->{'2fa_enabled'} || !$user->{'2fa_secret'}) {
|
||||||
|
abort(403);
|
||||||
|
}
|
||||||
|
$backups = $this->generateBackupCodes();
|
||||||
|
$user->{'2fa_backup_codes'} = json_encode($backups);
|
||||||
|
$user->save();
|
||||||
|
return redirect(route('settings.security.2fa.recovery'));
|
||||||
|
}
|
||||||
|
|
||||||
public function securityTwoFactorUpdate(Request $request)
|
public function securityTwoFactorUpdate(Request $request)
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
|
|
@ -38,7 +38,7 @@ class StatusActivityPubDeliver implements ShouldQueue
|
||||||
{
|
{
|
||||||
$status = $this->status;
|
$status = $this->status;
|
||||||
|
|
||||||
if($status->local == true || $status->url || $status->uri) {
|
if($status->local == false || $status->url || $status->uri) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,18 @@ class Helpers {
|
||||||
$activity = ['object' => $res];
|
$activity = ['object' => $res];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$idDomain = parse_url($res['id'], PHP_URL_HOST);
|
||||||
|
$urlDomain = parse_url($url, PHP_URL_HOST);
|
||||||
|
$actorDomain = parse_url($activity['object']['attributedTo'], PHP_URL_HOST);
|
||||||
|
|
||||||
|
if(
|
||||||
|
$idDomain !== $urlDomain ||
|
||||||
|
$actorDomain !== $urlDomain ||
|
||||||
|
$idDomain !== $actorDomain
|
||||||
|
) {
|
||||||
|
abort(400, 'Invalid object');
|
||||||
|
}
|
||||||
|
|
||||||
$profile = self::profileFirstOrNew($activity['object']['attributedTo']);
|
$profile = self::profileFirstOrNew($activity['object']['attributedTo']);
|
||||||
if(isset($activity['object']['inReplyTo']) && !empty($activity['object']['inReplyTo']) && $replyTo == true) {
|
if(isset($activity['object']['inReplyTo']) && !empty($activity['object']['inReplyTo']) && $replyTo == true) {
|
||||||
$reply_to = self::statusFirstOrFetch($activity['object']['inReplyTo'], false);
|
$reply_to = self::statusFirstOrFetch($activity['object']['inReplyTo'], false);
|
||||||
|
|
|
@ -167,12 +167,13 @@ class Inbox
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = DB::transaction(function() use($activity, $actor) {
|
$status = DB::transaction(function() use($activity, $actor, $url) {
|
||||||
$caption = str_limit(strip_tags($activity['content']), config('pixelfed.max_caption_length'));
|
$caption = str_limit(strip_tags($activity['content']), config('pixelfed.max_caption_length'));
|
||||||
$status = new Status;
|
$status = new Status;
|
||||||
$status->profile_id = $actor->id;
|
$status->profile_id = $actor->id;
|
||||||
$status->caption = $caption;
|
$status->caption = $caption;
|
||||||
$status->visibility = $status->scope = 'public';
|
$status->visibility = $status->scope = 'public';
|
||||||
|
$status->uri = $url;
|
||||||
$status->url = $url;
|
$status->url = $url;
|
||||||
$status->save();
|
$status->save();
|
||||||
return $status;
|
return $status;
|
||||||
|
@ -219,7 +220,7 @@ class Inbox
|
||||||
// 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' => $target->permalink().'#accepts/follows/',
|
'id' => $target->permalink().'#accepts/follows/' . $follower->id,
|
||||||
'type' => 'Accept',
|
'type' => 'Accept',
|
||||||
'actor' => $target->permalink(),
|
'actor' => $target->permalink(),
|
||||||
'object' => [
|
'object' => [
|
||||||
|
|
32
app/Util/ActivityPub/Validator/Accept.php
Normal file
32
app/Util/ActivityPub/Validator/Accept.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Util\ActivityPub\Validator;
|
||||||
|
|
||||||
|
use Validator;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class Accept {
|
||||||
|
|
||||||
|
public static function validate($payload)
|
||||||
|
{
|
||||||
|
$valid = Validator::make($payload, [
|
||||||
|
'@context' => 'required',
|
||||||
|
'id' => 'required|string',
|
||||||
|
'type' => [
|
||||||
|
'required',
|
||||||
|
Rule::in(['Accept'])
|
||||||
|
],
|
||||||
|
'actor' => 'required|url|active_url',
|
||||||
|
'object' => 'required',
|
||||||
|
'object.id' => 'required|url|active_url',
|
||||||
|
'object.type' => [
|
||||||
|
'required',
|
||||||
|
Rule::in(['Follow'])
|
||||||
|
],
|
||||||
|
'object.actor' => 'required|url|active_url',
|
||||||
|
'object.object' => 'required|url|active_url|same:actor',
|
||||||
|
])->passes();
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,6 @@ class RestrictedNames
|
||||||
'ftp',
|
'ftp',
|
||||||
'guest',
|
'guest',
|
||||||
'guests',
|
'guests',
|
||||||
'help',
|
|
||||||
'hostmaster',
|
'hostmaster',
|
||||||
'hostmaster',
|
'hostmaster',
|
||||||
'image',
|
'image',
|
||||||
|
@ -94,9 +93,6 @@ class RestrictedNames
|
||||||
'ssladmin',
|
'ssladmin',
|
||||||
'ssladministrator',
|
'ssladministrator',
|
||||||
'sslwebmaster',
|
'sslwebmaster',
|
||||||
'status',
|
|
||||||
'support',
|
|
||||||
'support',
|
|
||||||
'sys',
|
'sys',
|
||||||
'sysadmin',
|
'sysadmin',
|
||||||
'system',
|
'system',
|
||||||
|
@ -107,7 +103,6 @@ class RestrictedNames
|
||||||
'uucp',
|
'uucp',
|
||||||
'webmaster',
|
'webmaster',
|
||||||
'wpad',
|
'wpad',
|
||||||
'www',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public static $reserved = [
|
public static $reserved = [
|
||||||
|
@ -126,36 +121,60 @@ class RestrictedNames
|
||||||
'account',
|
'account',
|
||||||
'api',
|
'api',
|
||||||
'auth',
|
'auth',
|
||||||
|
'broadcast',
|
||||||
|
'broadcaster',
|
||||||
'css',
|
'css',
|
||||||
'checkpoint',
|
'checkpoint',
|
||||||
|
'collection',
|
||||||
|
'collections',
|
||||||
'c',
|
'c',
|
||||||
'i',
|
'cdn',
|
||||||
'dashboard',
|
'dashboard',
|
||||||
'deck',
|
'deck',
|
||||||
'discover',
|
'discover',
|
||||||
'docs',
|
'docs',
|
||||||
|
'error',
|
||||||
|
'explore',
|
||||||
'fonts',
|
'fonts',
|
||||||
'home',
|
'home',
|
||||||
|
'help',
|
||||||
|
'helpcenter',
|
||||||
|
'i',
|
||||||
'img',
|
'img',
|
||||||
'js',
|
'js',
|
||||||
|
'live',
|
||||||
'login',
|
'login',
|
||||||
'logout',
|
'logout',
|
||||||
'media',
|
'media',
|
||||||
|
'official',
|
||||||
'p',
|
'p',
|
||||||
'password',
|
'password',
|
||||||
|
'reset',
|
||||||
'report',
|
'report',
|
||||||
'reports',
|
'reports',
|
||||||
|
'robot',
|
||||||
|
'robots',
|
||||||
'search',
|
'search',
|
||||||
|
'send',
|
||||||
'settings',
|
'settings',
|
||||||
|
'status',
|
||||||
'statuses',
|
'statuses',
|
||||||
'site',
|
'site',
|
||||||
'sites',
|
'sites',
|
||||||
|
'static',
|
||||||
|
'story',
|
||||||
|
'stories',
|
||||||
|
'support',
|
||||||
|
'telescope',
|
||||||
'timeline',
|
'timeline',
|
||||||
'timelines',
|
'timelines',
|
||||||
'tour',
|
'tour',
|
||||||
'user',
|
'user',
|
||||||
'users',
|
'users',
|
||||||
'vendor',
|
'vendor',
|
||||||
|
'ws',
|
||||||
|
'wss',
|
||||||
|
'www',
|
||||||
'400',
|
'400',
|
||||||
'401',
|
'401',
|
||||||
'403',
|
'403',
|
||||||
|
|
|
@ -23,7 +23,7 @@ return [
|
||||||
| This value is the version of your PixelFed instance.
|
| This value is the version of your PixelFed instance.
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
'version' => '0.7.2',
|
'version' => '0.7.7',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -59,7 +59,7 @@ return [
|
||||||
*/
|
*/
|
||||||
'restricted_names' => [
|
'restricted_names' => [
|
||||||
'reserved_routes' => true,
|
'reserved_routes' => true,
|
||||||
'use_blacklist' => false,
|
'use_blacklist' => env('USERNAME_BLACKLIST', false),
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM php:7-apache
|
FROM php:7.2-apache
|
||||||
|
|
||||||
ARG COMPOSER_VERSION="1.6.5"
|
ARG COMPOSER_VERSION="1.6.5"
|
||||||
ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434"
|
ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM php:7-fpm
|
FROM php:7.2-fpm
|
||||||
|
|
||||||
ARG COMPOSER_VERSION="1.6.5"
|
ARG COMPOSER_VERSION="1.6.5"
|
||||||
ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434"
|
ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434"
|
||||||
|
|
BIN
public/js/components.js
vendored
BIN
public/js/components.js
vendored
Binary file not shown.
Binary file not shown.
15
resources/assets/js/components.js
vendored
15
resources/assets/js/components.js
vendored
|
@ -25,6 +25,13 @@ pixelfed.readmore = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
document.createEvent("TouchEvent");
|
||||||
|
$('body').addClass('touch');
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
window.InfiniteScroll = require('infinite-scroll');
|
window.InfiniteScroll = require('infinite-scroll');
|
||||||
window.filesize = require('filesize');
|
window.filesize = require('filesize');
|
||||||
window.Plyr = require('plyr');
|
window.Plyr = require('plyr');
|
||||||
|
@ -55,7 +62,7 @@ require('./components/statusform');
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Initalize Notification Helper
|
// Initialize Notification Helper
|
||||||
window.pixelfed.n = {};
|
window.pixelfed.n = {};
|
||||||
|
|
||||||
Vue.component(
|
Vue.component(
|
||||||
|
@ -137,10 +144,10 @@ window.pixelfed.copyToClipboard = (str) => {
|
||||||
const el = document.createElement('textarea');
|
const el = document.createElement('textarea');
|
||||||
el.value = str;
|
el.value = str;
|
||||||
el.setAttribute('readonly', '');
|
el.setAttribute('readonly', '');
|
||||||
el.style.position = 'absolute';
|
el.style.position = 'absolute';
|
||||||
el.style.left = '-9999px';
|
el.style.left = '-9999px';
|
||||||
document.body.appendChild(el);
|
document.body.appendChild(el);
|
||||||
const selected =
|
const selected =
|
||||||
document.getSelection().rangeCount > 0
|
document.getSelection().rangeCount > 0
|
||||||
? document.getSelection().getRangeAt(0)
|
? document.getSelection().getRangeAt(0)
|
||||||
: false;
|
: false;
|
||||||
|
@ -162,4 +169,4 @@ $(document).ready(function() {
|
||||||
const warningTitleCSS = 'color:red; font-size:60px; font-weight: bold; -webkit-text-stroke: 1px black;';
|
const warningTitleCSS = 'color:red; font-size:60px; font-weight: bold; -webkit-text-stroke: 1px black;';
|
||||||
const warningDescCSS = 'font-size: 18px;';
|
const warningDescCSS = 'font-size: 18px;';
|
||||||
console.log('%cStop!', warningTitleCSS);
|
console.log('%cStop!', warningTitleCSS);
|
||||||
console.log("%cThis is a browser feature intended for developers. If someone told you to copy and paste something here to enable a Pixelfed feature or \"hack\" someone's account, it is a scam and will give them access to your Pixelfed account.", warningDescCSS);
|
console.log("%cThis is a browser feature intended for developers. If someone told you to copy and paste something here to enable a Pixelfed feature or \"hack\" someone's account, it is a scam and will give them access to your Pixelfed account.", warningDescCSS);
|
||||||
|
|
|
@ -70,7 +70,7 @@ export default {
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
swal(
|
swal(
|
||||||
'Whoops! Something went wrong...',
|
'Whoops! Something went wrong...',
|
||||||
'An error occured, please try again later.',
|
'An error occurred, please try again later.',
|
||||||
'error'
|
'error'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -104,7 +104,7 @@ export default {
|
||||||
$('.postCommentsLoader .lds-ring')
|
$('.postCommentsLoader .lds-ring')
|
||||||
.attr('style','width:100%')
|
.attr('style','width:100%')
|
||||||
.addClass('pt-4 font-weight-bold text-muted')
|
.addClass('pt-4 font-weight-bold text-muted')
|
||||||
.text('An error occured, cannot fetch comments. Please try again later.');
|
.text('An error occurred, cannot fetch comments. Please try again later.');
|
||||||
} else {
|
} else {
|
||||||
switch(error.response.status) {
|
switch(error.response.status) {
|
||||||
case 401:
|
case 401:
|
||||||
|
@ -118,7 +118,7 @@ export default {
|
||||||
$('.postCommentsLoader .lds-ring')
|
$('.postCommentsLoader .lds-ring')
|
||||||
.attr('style','width:100%')
|
.attr('style','width:100%')
|
||||||
.addClass('pt-4 font-weight-bold text-muted')
|
.addClass('pt-4 font-weight-bold text-muted')
|
||||||
.text('An error occured, cannot fetch comments. Please try again later.');
|
.text('An error occurred, cannot fetch comments. Please try again later.');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-md-8 px-0 mx-0">
|
<div class="col-12 col-md-8 px-0 mx-0">
|
||||||
<div class="postPresenterLoader text-center">
|
<div class="postPresenterLoader text-center">
|
||||||
<div class="lds-ring"><div></div><div></div><div></div><div></div></div>
|
<div class="lds-ring"><div></div><div></div><div></div><div></div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="postPresenterContainer d-none d-flex justify-content-center align-items-center">
|
<div class="postPresenterContainer d-none d-flex justify-content-center align-items-center">
|
||||||
<div v-if="status.pf_type === 'photo'" class="w-100">
|
<div v-if="status.pf_type === 'photo'" class="w-100">
|
||||||
<photo-presenter :status="status"></photo-presenter>
|
<photo-presenter :status="status"></photo-presenter>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="status.pf_type === 'video'" class="w-100">
|
<div v-else-if="status.pf_type === 'video'" class="w-100">
|
||||||
|
@ -156,6 +156,7 @@
|
||||||
<input type="hidden" name="_token" value="">
|
<input type="hidden" name="_token" value="">
|
||||||
<input type="hidden" name="item" :value="statusId">
|
<input type="hidden" name="item" :value="statusId">
|
||||||
<input class="form-control" name="comment" placeholder="Add a comment..." autocomplete="off">
|
<input class="form-control" name="comment" placeholder="Add a comment..." autocomplete="off">
|
||||||
|
<input type="submit" value="Send" class="btn btn-primary comment-submit" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -164,10 +165,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<b-modal ref="likesModal"
|
<b-modal ref="likesModal"
|
||||||
id="l-modal"
|
id="l-modal"
|
||||||
hide-footer
|
hide-footer
|
||||||
centered
|
centered
|
||||||
title="Likes"
|
title="Likes"
|
||||||
body-class="list-group-flush p-0">
|
body-class="list-group-flush p-0">
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
|
@ -195,10 +196,10 @@
|
||||||
</infinite-loading>
|
</infinite-loading>
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
<b-modal ref="sharesModal"
|
<b-modal ref="sharesModal"
|
||||||
id="s-modal"
|
id="s-modal"
|
||||||
hide-footer
|
hide-footer
|
||||||
centered
|
centered
|
||||||
title="Shares"
|
title="Shares"
|
||||||
body-class="list-group-flush p-0">
|
body-class="list-group-flush p-0">
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
|
@ -281,7 +282,7 @@ export default {
|
||||||
$('head title').text(title);
|
$('head title').text(title);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
authCheck() {
|
authCheck() {
|
||||||
let authed = $('body').hasClass('loggedIn');
|
let authed = $('body').hasClass('loggedIn');
|
||||||
|
@ -339,7 +340,7 @@ export default {
|
||||||
$('.postPresenterContainer').removeClass('d-none');
|
$('.postPresenterContainer').removeClass('d-none');
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if(!error.response) {
|
if(!error.response) {
|
||||||
$('.postPresenterLoader .lds-ring').attr('style','width:100%').addClass('pt-4 font-weight-bold text-muted').text('An error occured, cannot fetch media. Please try again later.');
|
$('.postPresenterLoader .lds-ring').attr('style','width:100%').addClass('pt-4 font-weight-bold text-muted').text('An error occurred, cannot fetch media. Please try again later.');
|
||||||
} else {
|
} else {
|
||||||
switch(error.response.status) {
|
switch(error.response.status) {
|
||||||
case 401:
|
case 401:
|
||||||
|
@ -350,7 +351,7 @@ export default {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$('.postPresenterLoader .lds-ring').attr('style','width:100%').addClass('pt-4 font-weight-bold text-muted').text('An error occured, cannot fetch media. Please try again later.');
|
$('.postPresenterLoader .lds-ring').attr('style','width:100%').addClass('pt-4 font-weight-bold text-muted').text('An error occurred, cannot fetch media. Please try again later.');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,4 +511,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -156,22 +156,22 @@
|
||||||
<div class="media-body font-weight-light small">
|
<div class="media-body font-weight-light small">
|
||||||
<div v-if="n.type == 'favourite'">
|
<div v-if="n.type == 'favourite'">
|
||||||
<p class="my-0">
|
<p class="my-0">
|
||||||
<a :href="n.account.url" class="font-weight-bold text-dark">{{n.account.username}}</a> liked your <a class="font-weight-bold" v-bind:href="replyUrl(n.status)">post</a>.
|
<a :href="n.account.url" class="font-weight-bold text-dark word-break">{{n.account.username}}</a> liked your <a class="font-weight-bold" v-bind:href="replyUrl(n.status)">post</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="n.type == 'comment'">
|
<div v-else-if="n.type == 'comment'">
|
||||||
<p class="my-0">
|
<p class="my-0">
|
||||||
<a :href="n.account.url" class="font-weight-bold text-dark">{{n.account.username}}</a> commented on your <a class="font-weight-bold" v-bind:href="replyUrl(n.status)">post</a>.
|
<a :href="n.account.url" class="font-weight-bold text-dark word-break">{{n.account.username}}</a> commented on your <a class="font-weight-bold" v-bind:href="replyUrl(n.status)">post</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="n.type == 'mention'">
|
<div v-else-if="n.type == 'mention'">
|
||||||
<p class="my-0">
|
<p class="my-0">
|
||||||
<a :href="n.account.url" class="font-weight-bold text-dark">{{n.account.username}}</a> <a class="font-weight-bold" v-bind:href="mentionUrl(n.status)">mentioned</a> you.
|
<a :href="n.account.url" class="font-weight-bold text-dark word-break">{{n.account.username}}</a> <a class="font-weight-bold" v-bind:href="mentionUrl(n.status)">mentioned</a> you.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="n.type == 'follow'">
|
<div v-else-if="n.type == 'follow'">
|
||||||
<p class="my-0">
|
<p class="my-0">
|
||||||
<a :href="n.account.url" class="font-weight-bold text-dark">{{n.account.username}}</a> followed you.
|
<a :href="n.account.url" class="font-weight-bold text-dark word-break">{{n.account.username}}</a> followed you.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -211,6 +211,9 @@
|
||||||
.cursor-pointer {
|
.cursor-pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.word-break {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -96,7 +96,7 @@ $(document).ready(function() {
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
swal(
|
swal(
|
||||||
'Something went wrong!',
|
'Something went wrong!',
|
||||||
'An error occured, please try again later.',
|
'An error occurred, please try again later.',
|
||||||
'error'
|
'error'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
20
resources/assets/sass/custom.scss
vendored
20
resources/assets/sass/custom.scss
vendored
|
@ -267,6 +267,26 @@ body, button, input, textarea {
|
||||||
.card {
|
.card {
|
||||||
box-shadow: 0 2px 6px 0 hsla(0, 0%, 0%, 0.2);
|
box-shadow: 0 2px 6px 0 hsla(0, 0%, 0%, 0.2);
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
|
.comment-submit {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 12px;
|
||||||
|
right: 20px;
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.touch .card {
|
||||||
|
input[name="comment"] {
|
||||||
|
padding-right: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment-submit {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.box-shadow {
|
.box-shadow {
|
||||||
|
|
35
resources/lang/vendor/backup/cs/notifications.php
vendored
Normal file
35
resources/lang/vendor/backup/cs/notifications.php
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'exception_message' => 'Zpráva výjimky: :message',
|
||||||
|
'exception_trace' => 'Stopa výjimky: :trace',
|
||||||
|
'exception_message_title' => 'Zpráva výjimky',
|
||||||
|
'exception_trace_title' => 'Stopa výjimky',
|
||||||
|
|
||||||
|
'backup_failed_subject' => 'Záloha :application_name neuspěla',
|
||||||
|
'backup_failed_body' => 'Důležité: Při záloze :application_name se vyskytla chyba',
|
||||||
|
|
||||||
|
'backup_successful_subject' => 'Úspěšná nová záloha :application_name',
|
||||||
|
'backup_successful_subject_title' => 'Úspěšná nová záloha!',
|
||||||
|
'backup_successful_body' => 'Dobrá zpráva, na disku jménem :disk_name byla úspěšně vytvořena nová záloha :application_name.',
|
||||||
|
|
||||||
|
'cleanup_failed_subject' => 'Vyčištění záloh :application_name neuspělo.',
|
||||||
|
'cleanup_failed_body' => 'Při vyčištění záloh :application_name se vyskytla chyba',
|
||||||
|
|
||||||
|
'cleanup_successful_subject' => 'Vyčištění záloh :application_name úspěšné',
|
||||||
|
'cleanup_successful_subject_title' => 'Vyčištění záloh bylo úspěšné!',
|
||||||
|
'cleanup_successful_body' => 'Vyčištění záloh :application_name na disku jménem :disk_name bylo úspěšné.',
|
||||||
|
|
||||||
|
'healthy_backup_found_subject' => 'Zálohy pro :application_name na disku :disk_name jsou zdravé',
|
||||||
|
'healthy_backup_found_subject_title' => 'Zálohy pro :application_name jsou zdravé',
|
||||||
|
'healthy_backup_found_body' => 'Zálohy pro :application_name jsou považovány za zdravé. Dobrá práce!',
|
||||||
|
|
||||||
|
'unhealthy_backup_found_subject' => 'Důležité: Zálohy pro :application_name jsou nezdravé',
|
||||||
|
'unhealthy_backup_found_subject_title' => 'Důležité: Zálohy pro :application_name jsou nezdravé. :problem',
|
||||||
|
'unhealthy_backup_found_body' => 'Zálohy pro :application_name na disku :disk_name Jsou nezdravé.',
|
||||||
|
'unhealthy_backup_found_not_reachable' => 'Nelze se dostat k cíli zálohy. :error',
|
||||||
|
'unhealthy_backup_found_empty' => 'Tato aplikace nemá vůbec žádné zálohy.',
|
||||||
|
'unhealthy_backup_found_old' => 'Poslední záloha vytvořená dne :date je považována za příliš starou.',
|
||||||
|
'unhealthy_backup_found_unknown' => 'Omlouváme se, nemůžeme určit přesný důvod.',
|
||||||
|
'unhealthy_backup_found_full' => 'Zálohy zabírají příliš mnoho místa na disku. Aktuální využití disku je :disk_usage, což je vyšší než povolený limit :disk_limit.',
|
||||||
|
];
|
|
@ -6,18 +6,30 @@
|
||||||
<h3 class="font-weight-bold">Account Settings</h3>
|
<h3 class="font-weight-bold">Account Settings</h3>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<form method="post">
|
<div class="form-group row">
|
||||||
@csrf
|
<div class="col-sm-3">
|
||||||
<div class="form-group row">
|
<img src="{{Auth::user()->profile->avatarUrl()}}" width="38px" height="38px" class="rounded-circle float-right">
|
||||||
<div class="col-sm-3">
|
</div>
|
||||||
<img src="{{Auth::user()->profile->avatarUrl()}}" width="38px" height="38px" class="rounded-circle float-right">
|
<div class="col-sm-9">
|
||||||
</div>
|
<p class="lead font-weight-bold mb-0">{{Auth::user()->username}}</p>
|
||||||
<div class="col-sm-9">
|
<p><a href="#" class="font-weight-bold change-profile-photo" data-toggle="collapse" data-target="#avatarCollapse" aria-expanded="false" aria-controls="avatarCollapse">Change Profile Photo</a></p>
|
||||||
<p class="lead font-weight-bold mb-0">{{Auth::user()->username}}</p>
|
<div class="collapse" id="avatarCollapse">
|
||||||
<p class="mb-0"><a href="#" class="font-weight-bold change-profile-photo">Change Profile Photo</a></p>
|
<form method="post" action="/settings/avatar" enctype="multipart/form-data">
|
||||||
<p><span class="small font-weight-bold">Max avatar size: <span id="maxAvatarSize"></span></span></p>
|
@csrf
|
||||||
|
<div class="card card-body">
|
||||||
|
<div class="custom-file mb-1">
|
||||||
|
<input type="file" name="avatar" class="custom-file-input" id="avatarInput">
|
||||||
|
<label class="custom-file-label" for="avatarInput">Select a profile photo</label>
|
||||||
|
</div>
|
||||||
|
<p><span class="small font-weight-bold">Must be a jpeg or png. Max avatar size: <span id="maxAvatarSize"></span></span></p>
|
||||||
|
<p class="mb-0"><button type="submit" class="btn btn-primary px-4 py-0 font-weight-bold">Upload</button></p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<form method="post">
|
||||||
|
@csrf
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="name" class="col-sm-3 col-form-label font-weight-bold text-right">Name</label>
|
<label for="name" class="col-sm-3 col-form-label font-weight-bold text-right">Name</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
|
@ -118,45 +130,5 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#maxAvatarSize').text(filesize({{config('pixelfed.max_avatar_size') * 1024}}, {round: 0}));
|
$('#maxAvatarSize').text(filesize({{config('pixelfed.max_avatar_size') * 1024}}, {round: 0}));
|
||||||
|
|
||||||
$(document).on('click', '.change-profile-photo', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
swal({
|
|
||||||
title: 'Upload Photo',
|
|
||||||
content: {
|
|
||||||
element: 'input',
|
|
||||||
attributes: {
|
|
||||||
placeholder: 'Upload your photo.',
|
|
||||||
type: 'file',
|
|
||||||
name: 'photoUpload',
|
|
||||||
id: 'photoUploadInput'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
buttons: {
|
|
||||||
confirm: {
|
|
||||||
text: 'Upload'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if(!res) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const input = $('#photoUploadInput')[0];
|
|
||||||
const photo = input.files[0];
|
|
||||||
const form = new FormData();
|
|
||||||
form.append("upload", photo);
|
|
||||||
|
|
||||||
axios.post('/api/v1/avatar/update', form, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
swal('Success', 'Your photo has been successfully updated! It may take a few minutes to update across the site.', 'success');
|
|
||||||
}).catch((res) => {
|
|
||||||
let msg = res.response.data.errors.upload[0];
|
|
||||||
swal('Something went wrong', msg, 'error');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<p class="">When you press the button below, your photos, comments, likes, friendships and all other data will be removed permanently and will not be recoverable. If you decide to create another Pixelfed account in the future, you cannot sign up with the same username again on this instance.</p>
|
<p class="">When you press the button below, your photos, comments, likes, friendships and all other data will be removed permanently and will not be recoverable. If you decide to create another Pixelfed account in the future, you cannot sign up with the same username again on this instance.</p>
|
||||||
|
|
||||||
<div class="alert alert-danger my-5">
|
<div class="alert alert-danger my-5">
|
||||||
<span class="font-weight-bold">Warning:</span> Some remote servers may contain your public data (statuses, avatars, ect) and will not be deleted until federation support is launched.
|
<span class="font-weight-bold">Warning:</span> Some remote servers may contain your public data (statuses, avatars, etc) and will not be deleted until federation support is launched.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -7,16 +7,26 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
@if(count($codes) > 0)
|
||||||
<p class="lead pb-3">
|
<p class="lead pb-3">
|
||||||
Each code can only be used once.
|
Each code can only be used once.
|
||||||
</p>
|
</p>
|
||||||
|
<ul class="list-group">
|
||||||
<p class="lead"></p>
|
@foreach($codes as $code)
|
||||||
<ul class="list-group">
|
<li class="list-group-item"><code>{{$code}}</code></li>
|
||||||
@foreach($codes as $code)
|
@endforeach
|
||||||
<li class="list-group-item"><code>{{$code}}</code></li>
|
</ul>
|
||||||
@endforeach
|
@else
|
||||||
</ul>
|
<div class="pt-5">
|
||||||
|
<h4 class="font-weight-bold">You are out of recovery codes</h4>
|
||||||
|
<p class="lead">Generate more recovery codes and store them in a safe place.</p>
|
||||||
|
<p>
|
||||||
|
<form method="post">
|
||||||
|
@csrf
|
||||||
|
<button type="submit" class="btn btn-primary font-weight-bold">Generate Recovery Codes</button>
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
@endsection
|
@endsection
|
|
@ -64,7 +64,7 @@
|
||||||
<p>
|
<p>
|
||||||
<a class="text-dark font-weight-bold" data-toggle="collapse" href="#collapse5" role="button" aria-expanded="false" aria-controls="collapse5">
|
<a class="text-dark font-weight-bold" data-toggle="collapse" href="#collapse5" role="button" aria-expanded="false" aria-controls="collapse5">
|
||||||
<i class="fas fa-chevron-down mr-2"></i>
|
<i class="fas fa-chevron-down mr-2"></i>
|
||||||
I recieved an email that I created an account, but I never signed up for one.
|
I received an email that I created an account, but I never signed up for one.
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse" id="collapse5">
|
<div class="collapse" id="collapse5">
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
|
|
|
@ -354,7 +354,7 @@ $(document).on('change', '.file-input', function(e) {
|
||||||
el.remove();
|
el.remove();
|
||||||
}
|
}
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
swal('Oops, something went wrong!', 'An unexpected error occured.', 'error');
|
swal('Oops, something went wrong!', 'An unexpected error occurred.', 'error');
|
||||||
});
|
});
|
||||||
io.value = null;
|
io.value = null;
|
||||||
});
|
});
|
||||||
|
@ -478,7 +478,7 @@ $(document).on('click', '#create', function(e) {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
window.location.href = data;
|
window.location.href = data;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
swal('Oops, something went wrong!', 'An unexpected error occured.', 'error');
|
swal('Oops, something went wrong!', 'An unexpected error occurred.', 'error');
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
swal('Success!', 'You have successfully updated your post', 'success');
|
swal('Success!', 'You have successfully updated your post', 'success');
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
swal('Something went wrong', 'An error occured, please try again later', 'error');
|
swal('Something went wrong', 'An error occurred, please try again later', 'error');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
|
|
||||||
Route::group(['prefix' => 'report'], function () {
|
Route::group(['prefix' => 'report'], function () {
|
||||||
Route::get('/', 'ReportController@showForm')->name('report.form');
|
Route::get('/', 'ReportController@showForm')->name('report.form');
|
||||||
Route::post('/', 'ReportController@formStore')->middleware('throttle:100,1440');
|
Route::post('/', 'ReportController@formStore')->middleware('throttle:10,5');
|
||||||
Route::get('not-interested', 'ReportController@notInterestedForm')->name('report.not-interested');
|
Route::get('not-interested', 'ReportController@notInterestedForm')->name('report.not-interested');
|
||||||
Route::get('spam', 'ReportController@spamForm')->name('report.spam');
|
Route::get('spam', 'ReportController@spamForm')->name('report.spam');
|
||||||
Route::get('spam/comment', 'ReportController@spamCommentForm')->name('report.spam.comment');
|
Route::get('spam/comment', 'ReportController@spamCommentForm')->name('report.spam.comment');
|
||||||
|
@ -120,7 +120,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
->name('settings');
|
->name('settings');
|
||||||
Route::post('home', 'SettingsController@homeUpdate')->middleware('throttle:250,1440');
|
Route::post('home', 'SettingsController@homeUpdate')->middleware('throttle:250,1440');
|
||||||
Route::get('avatar', 'SettingsController@avatar')->name('settings.avatar');
|
Route::get('avatar', 'SettingsController@avatar')->name('settings.avatar');
|
||||||
Route::post('avatar', 'AvatarController@store')->middleware('throttle:50,1440');
|
Route::post('avatar', 'AvatarController@store');
|
||||||
Route::get('password', 'SettingsController@password')->name('settings.password')->middleware('dangerzone');
|
Route::get('password', 'SettingsController@password')->name('settings.password')->middleware('dangerzone');
|
||||||
Route::post('password', 'SettingsController@passwordUpdate')->middleware(['throttle:2,1440','dangerzone']);
|
Route::post('password', 'SettingsController@passwordUpdate')->middleware(['throttle:2,1440','dangerzone']);
|
||||||
Route::get('email', 'SettingsController@email')->name('settings.email');
|
Route::get('email', 'SettingsController@email')->name('settings.email');
|
||||||
|
@ -166,6 +166,10 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
'2fa/recovery-codes',
|
'2fa/recovery-codes',
|
||||||
'SettingsController@securityTwoFactorRecoveryCodes'
|
'SettingsController@securityTwoFactorRecoveryCodes'
|
||||||
)->name('settings.security.2fa.recovery');
|
)->name('settings.security.2fa.recovery');
|
||||||
|
Route::post(
|
||||||
|
'2fa/recovery-codes',
|
||||||
|
'SettingsController@securityTwoFactorRecoveryCodesRegenerate'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('applications', 'SettingsController@applications')->name('settings.applications');
|
Route::get('applications', 'SettingsController@applications')->name('settings.applications');
|
||||||
|
|
55
tests/Unit/ActivityPub/AcceptVerbTest.php
Normal file
55
tests/Unit/ActivityPub/AcceptVerbTest.php
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Illuminate\Foundation\Testing\WithFaker;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use App\Util\ActivityPub\Validator\Accept;
|
||||||
|
|
||||||
|
class AcceptVerbTest extends TestCase
|
||||||
|
{
|
||||||
|
protected $validAccept;
|
||||||
|
protected $invalidAccept;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->validAccept = [
|
||||||
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id' => 'https://example.org/og/b3e4a40b-0b26-4c5a-9079-094bd633fab7',
|
||||||
|
'type' => 'Accept',
|
||||||
|
'actor' => 'https://example.org/u/alice',
|
||||||
|
'object' => [
|
||||||
|
'id' => 'https://example.net/u/bob#follows/bb27f601-ddb9-4567-8f16-023d90605ca9',
|
||||||
|
'type' => 'Follow',
|
||||||
|
'actor' => 'https://example.net/u/bob',
|
||||||
|
'object' => 'https://example.org/u/alice'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$this->invalidAccept = [
|
||||||
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id' => 'https://example.org/og/b3e4a40b-0b26-4c5a-9079-094bd633fab7',
|
||||||
|
'type' => 'Accept2',
|
||||||
|
'actor' => 'https://example.org/u/alice',
|
||||||
|
'object' => [
|
||||||
|
'id' => 'https://example.net/u/bob#follows/bb27f601-ddb9-4567-8f16-023d90605ca9',
|
||||||
|
'type' => 'Follow',
|
||||||
|
'actor' => 'https://example.net/u/bob',
|
||||||
|
'object' => 'https://example.org/u/alice'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function basic_accept()
|
||||||
|
{
|
||||||
|
$this->assertTrue(Accept::validate($this->validAccept));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function invalid_accept()
|
||||||
|
{
|
||||||
|
$this->assertFalse(Accept::validate($this->invalidAccept));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue