diff --git a/.dockerignore b/.dockerignore index e47e3356b..70376cdf4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,6 @@ -storage data Dockerfile +contrib/docker/Dockerfile.* docker-compose*.yml .dockerignore .git diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 5a04578c1..000000000 --- a/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM php:7.2.6-fpm-alpine - -ARG COMPOSER_VERSION="1.6.5" -ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434" - -RUN apk add --no-cache --virtual .build build-base autoconf imagemagick-dev libtool && \ - apk --no-cache add imagemagick git && \ - docker-php-ext-install pdo_mysql pcntl bcmath && \ - pecl install imagick && \ - docker-php-ext-enable imagick pcntl imagick && \ - curl -LsS https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar -o /tmp/composer.phar && \ - echo "${COMPOSER_CHECKSUM} /tmp/composer.phar" | sha256sum -c - && \ - install -m0755 -o root -g root /tmp/composer.phar /usr/bin/composer.phar && \ - ln -sf /usr/bin/composer.phar /usr/bin/composer && \ - rm /tmp/composer.phar && \ - apk --no-cache del --purge .build - -COPY . /var/www/html/ - -WORKDIR /var/www/html -RUN install -d -m0755 -o www-data -g www-data \ - /var/www/html/storage \ - /var/www/html/storage/framework \ - /var/www/html/storage/logs \ - /var/www/html/storage/framework/sessions \ - /var/www/html/storage/framework/views \ - /var/www/html/storage/framework/cache && \ - composer install --prefer-source --no-interaction - -VOLUME ["/var/www/html"] -ENV PATH="~/.composer/vendor/bin:./vendor/bin:${PATH}" diff --git a/Dockerfile b/Dockerfile new file mode 120000 index 000000000..2f722aa37 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +contrib/docker/Dockerfile.apache \ No newline at end of file diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index f9ba3b648..5217a9925 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -65,7 +65,7 @@ class RegisterController extends Controller ]; $rules = [ - 'name' => 'required|string|max:255', + 'name' => 'required|string|max' . config('pixelfed.max_name_length'), 'username' => $usernameRules, 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index ab8f35ce9..14eced67c 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -30,8 +30,8 @@ class SettingsController extends Controller public function homeUpdate(Request $request) { $this->validate($request, [ - 'name' => 'required|string|max:30', - 'bio' => 'nullable|string|max:125', + 'name' => 'required|string|max:' . config('pixelfed.max_name_length'), + 'bio' => 'nullable|string|max:' . config('pixelfed.max_bio_length') 'website' => 'nullable|url', 'email' => 'nullable|email' ]); diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 57a7e41c1..6a9299939 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -21,17 +21,33 @@ class StatusController extends Controller ->withCount(['likes', 'comments', 'media']) ->findOrFail($id); - if(!$status->media_path && $status->in_reply_to_id) { - return redirect($status->url()); - } - if($request->wantsJson() && config('pixelfed.activitypub_enabled')) { return $this->showActivityPub($request, $status); } + $template = $this->detectTemplate($status); + $replies = Status::whereInReplyToId($status->id)->simplePaginate(30); - return view('status.show', compact('user', 'status', 'replies')); + return view($template, compact('user', 'status', 'replies')); + } + + protected function detectTemplate($status) + { + $template = Cache::rememberForever('template:status:type:'.$status->id, function () use($status) { + $template = 'status.show.photo'; + if(!$status->media_path && $status->in_reply_to_id) { + $template = 'status.reply'; + } + if($status->media->count() > 1) { + $template = 'status.show.album'; + } + if($status->viewType() == 'video') { + $template = 'status.show.video'; + } + return $template; + }); + return $template; } public function compose() @@ -42,11 +58,7 @@ class StatusController extends Controller public function store(Request $request) { - if(Auth::check() == false) - { - abort(403); - } - + $this->authCheck(); $user = Auth::user(); $size = Media::whereUserId($user->id)->sum('size') / 1000; @@ -56,7 +68,7 @@ class StatusController extends Controller } $this->validate($request, [ - 'photo.*' => 'required|mimes:jpeg,png,bmp,gif|max:' . config('pixelfed.max_photo_size'), + 'photo.*' => 'required|mimes:jpeg,png,gif|max:' . config('pixelfed.max_photo_size'), 'caption' => 'string|max:' . config('pixelfed.max_caption_length'), 'cw' => 'nullable|string', 'filter_class' => 'nullable|string', @@ -83,11 +95,13 @@ class StatusController extends Controller foreach ($photos as $k => $v) { $storagePath = "public/m/{$monthHash}/{$userHash}"; $path = $v->store($storagePath); + $hash = \hash_file('sha256', $v); $media = new Media; $media->status_id = $status->id; $media->profile_id = $profile->id; $media->user_id = $user->id; $media->media_path = $path; + $media->original_sha256 = $hash; $media->size = $v->getClientSize(); $media->mime = $v->getClientMimeType(); $media->filter_class = $request->input('filter_class'); @@ -172,6 +186,57 @@ class StatusController extends Controller return response(json_encode($res['data']))->header('Content-Type', 'application/activity+json'); } + public function edit(Request $request, $username, $id) + { + $this->authCheck(); + $user = Auth::user()->profile; + $status = Status::whereProfileId($user->id) + ->with(['media']) + ->findOrFail($id); + return view('status.edit', compact('user', 'status')); + } + + + public function editStore(Request $request, $username, $id) + { + $this->authCheck(); + $user = Auth::user()->profile; + $status = Status::whereProfileId($user->id) + ->with(['media']) + ->findOrFail($id); + + $this->validate($request, [ + 'id' => 'required|integer|min:1', + 'caption' => 'nullable', + 'filter' => 'nullable|alpha_dash|max:30' + ]); + + $id = $request->input('id'); + $caption = $request->input('caption'); + $filter = $request->input('filter'); + + $media = Media::whereProfileId($user->id) + ->whereStatusId($status->id) + ->find($id); + + $changed = false; + + if($media->caption != $caption) { + $media->caption = $caption; + $changed = true; + } + + if($media->filter_class != $filter) { + $media->filter_class = $filter; + $changed = true; + } + + if($changed === true) { + $media->save(); + } + return response()->json([], 200); + } + protected function authCheck() { if(Auth::check() == false) diff --git a/app/Http/Controllers/StoryController.php b/app/Http/Controllers/StoryController.php new file mode 100644 index 000000000..aafaa107e --- /dev/null +++ b/app/Http/Controllers/StoryController.php @@ -0,0 +1,11 @@ +profile->id; // TODO: Use redis for timelines - $following = Follower::whereProfileId(Auth::user()->profile->id)->pluck('following_id'); - $following->push(Auth::user()->profile->id); + $following = Follower::whereProfileId($pid)->pluck('following_id'); + $following->push($pid); + $filtered = UserFilter::whereUserId($pid) + ->whereFilterableType('App\Profile') + ->whereIn('filter_type', ['mute', 'block']) + ->pluck('filterable_id'); $timeline = Status::whereIn('profile_id', $following) + ->whereNotIn('profile_id', $filtered) ->orderBy('id','desc') ->withCount(['comments', 'likes']) ->simplePaginate(20); @@ -30,8 +36,18 @@ class TimelineController extends Controller { // TODO: Use redis for timelines // $timeline = Timeline::build()->local(); + $pid = Auth::user()->profile->id; + + $filtered = UserFilter::whereUserId($pid) + ->whereFilterableType('App\Profile') + ->whereIn('filter_type', ['mute', 'block']) + ->pluck('filterable_id'); + $private = Profile::whereIsPrivate(true)->pluck('id'); + $filtered = $filtered->merge($private); $timeline = Status::whereHas('media') + ->whereNotIn('profile_id', $filtered) ->whereNull('in_reply_to_id') + ->whereNull('reblog_of_id') ->withCount(['comments', 'likes']) ->orderBy('id','desc') ->simplePaginate(20); diff --git a/app/Jobs/ImageOptimizePipeline/ImageUpdate.php b/app/Jobs/ImageOptimizePipeline/ImageUpdate.php index 5b21ea7e9..482176bec 100644 --- a/app/Jobs/ImageOptimizePipeline/ImageUpdate.php +++ b/app/Jobs/ImageOptimizePipeline/ImageUpdate.php @@ -16,6 +16,12 @@ class ImageUpdate implements ShouldQueue protected $media; + protected $protectedMimes = [ + 'image/gif', + 'image/bmp', + 'video/mp4' + ]; + /** * Create a new job instance. * @@ -37,9 +43,9 @@ class ImageUpdate implements ShouldQueue $path = storage_path('app/'. $media->media_path); $thumb = storage_path('app/'. $media->thumbnail_path); try { - ImageOptimizer::optimize($thumb); - if($media->mime !== 'image/gif') + if(!in_array($media->mime, $this->protectedMimes)) { + ImageOptimizer::optimize($thumb); ImageOptimizer::optimize($path); } } catch (Exception $e) { diff --git a/app/Jobs/RemoteFollowPipeline/RemoteFollowImportRecent.php b/app/Jobs/RemoteFollowPipeline/RemoteFollowImportRecent.php index 1cb6a7828..9341babcb 100644 --- a/app/Jobs/RemoteFollowPipeline/RemoteFollowImportRecent.php +++ b/app/Jobs/RemoteFollowPipeline/RemoteFollowImportRecent.php @@ -13,6 +13,7 @@ use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use App\Jobs\StatusPipeline\NewStatusPipeline; +use App\Jobs\ImageOptimizePipeline\ImageThumbnail; class RemoteFollowImportRecent implements ShouldQueue { @@ -216,7 +217,9 @@ class RemoteFollowImportRecent implements ShouldQueue $media->size = 0; $media->mime = $mime; $media->save(); - + + ImageThumbnail::dispatch($media); + return true; } catch (Exception $e) { return false; diff --git a/app/Profile.php b/app/Profile.php index c620582b1..4487f81b6 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -143,7 +143,11 @@ class Profile extends Model public function statusCount() { - return $this->statuses()->whereHas('media')->count(); + return $this->statuses() + ->whereHas('media') + ->whereNull('in_reply_to_id') + ->whereNull('reblog_of_id') + ->count(); } public function recommendFollowers() @@ -159,6 +163,7 @@ class Profile extends Model ->whereNotIn('following_id', $follows) ->whereIn('profile_id', $following) ->orderByRaw('rand()') + ->distinct('id') ->limit(3) ->pluck('following_id'); $recommended = []; diff --git a/app/Report.php b/app/Report.php index 879a8df36..495f400ed 100644 --- a/app/Report.php +++ b/app/Report.php @@ -6,6 +6,8 @@ use Illuminate\Database\Eloquent\Model; class Report extends Model { + protected $dates = ['admin_seen']; + public function url() { return url('/i/admin/reports/show/' . $this->id); diff --git a/app/Util/ActivityPub/Concern/HTTPSignature.php b/app/Util/ActivityPub/Concern/HTTPSignature.php new file mode 100644 index 000000000..aa4f1fe9a --- /dev/null +++ b/app/Util/ActivityPub/Concern/HTTPSignature.php @@ -0,0 +1,94 @@ +is_url === false) { + return true; + } + + $url = $this->profile; + try { + $url = filter_var($url, FILTER_VALIDATE_URL); + $parsed = parse_url($url, PHP_URL_HOST); + if(!$parsed || in_array($parsed, $this->localhosts)) { + return false; + } + } catch (Exception $e) { + return false; + } + return true; + } + + public function fetchPublicKey($profile, bool $is_url = true) + { + $this->profile = $profile; + $this->is_url = $is_url; + $valid = $this->validateUrl(); + if(!$valid) { + throw new \Exception('Invalid URL provided'); + } + if($is_url && isset($profile->public_key) && $profile->public_key) { + return $profile->public_key; + } + + try { + $url = $this->profile; + $res = Zttp::timeout(30)->withHeaders([ + 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + 'User-Agent' => 'PixelFedBot v0.1 - https://pixelfed.org' + ])->get($url); + $actor = json_decode($res->getBody(), true); + } catch (Exception $e) { + throw new Exception('Unable to fetch public key'); + } + + return $actor['publicKey']['publicKeyPem']; + } + + public function sendSignedObject($senderProfile, $url, $body) + { + $profile = $senderProfile; + $context = new Context([ + 'keys' => [$profile->keyId() => $profile->private_key], + 'algorithm' => 'rsa-sha256', + 'headers' => ['(request-target)', 'Date'], + ]); + + $handlerStack = GuzzleHttpSignatures::defaultHandlerFromContext($context); + $client = new Client(['handler' => $handlerStack]); + + $headers = [ + 'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + 'Date' => date('D, d M Y h:i:s') . ' GMT', + 'Content-Type' => 'application/activity+json', + 'User-Agent' => 'PixelFedBot - https://pixelfed.org' + ]; + + $response = $client->post($url, [ + 'options' => [ + 'allow_redirects' => false, + 'verify' => true, + 'timeout' => 30 + ], + 'headers' => $headers, + 'body' => $body + ]); + + return $response->getBody(); + } + + +} \ No newline at end of file diff --git a/config/pixelfed.php b/config/pixelfed.php index b33c6c885..b675f4080 100644 --- a/config/pixelfed.php +++ b/config/pixelfed.php @@ -108,6 +108,26 @@ return [ */ 'max_caption_length' => env('MAX_CAPTION_LENGTH', 500), + /* + |-------------------------------------------------------------------------- + | Bio length limit + |-------------------------------------------------------------------------- + | + | Change the bio length limit for user profiles. + | + */ + 'max_bio_length' => env('MAX_BIO_LENGTH', 125), + + /* + |-------------------------------------------------------------------------- + | User name length limit + |-------------------------------------------------------------------------- + | + | Change the length limit for user names. + | + */ + 'max_name_length' => env('MAX_NAME_LENGTH', 30), + /* |-------------------------------------------------------------------------- | Album size limit @@ -138,4 +158,4 @@ return [ */ 'image_quality' => (int) env('IMAGE_QUALITY', 80), -]; \ No newline at end of file +]; diff --git a/config/trustedproxy.php b/config/trustedproxy.php new file mode 100644 index 000000000..0a0776ada --- /dev/null +++ b/config/trustedproxy.php @@ -0,0 +1,27 @@ +getClientIp() + * always gets the originating client IP, no matter + * how many proxies that client's request has + * subsequently passed through. + */ + 'proxies' => explode(',', env('TRUST_PROXIES', '')), +]; diff --git a/contrib/docker/Dockerfile.apache b/contrib/docker/Dockerfile.apache new file mode 100644 index 000000000..481db4647 --- /dev/null +++ b/contrib/docker/Dockerfile.apache @@ -0,0 +1,59 @@ +FROM php:7-apache + +ARG COMPOSER_VERSION="1.6.5" +ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434" + +RUN apt-get update \ + && apt-get install -y --no-install-recommends git \ + optipng pngquant jpegoptim gifsicle \ + libfreetype6 libjpeg62-turbo libpng16-16 libxpm4 libvpx4 libmagickwand-6.q16-3 \ + libfreetype6-dev libjpeg62-turbo-dev libpng-dev libxpm-dev libvpx-dev libmagickwand-dev \ + && docker-php-source extract \ + && docker-php-ext-configure gd \ + --with-freetype-dir=/usr/lib/x86_64-linux-gnu/ \ + --with-jpeg-dir=/usr/lib/x86_64-linux-gnu/ \ + --with-xpm-dir=/usr/lib/x86_64-linux-gnu/ \ + --with-vpx-dir=/usr/lib/x86_64-linux-gnu/ \ + && docker-php-ext-install pdo_mysql pcntl gd exif bcmath \ + && pecl install imagick \ + && docker-php-ext-enable imagick pcntl imagick gd exif \ + && a2enmod rewrite \ + && curl -LsS https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar -o /usr/bin/composer \ + && echo "${COMPOSER_CHECKSUM} /usr/bin/composer" | sha256sum -c - \ + && chmod 755 /usr/bin/composer \ + && apt-get autoremove --purge -y \ + libfreetype6-dev libjpeg62-turbo-dev libpng-dev libxpm-dev libvpx-dev libmagickwand-dev \ + && rm -rf /var/cache/apt \ + && docker-php-source delete + +ENV PATH="~/.composer/vendor/bin:./vendor/bin:${PATH}" + +COPY . /var/www/ + +WORKDIR /var/www/ +RUN cp -r storage storage.skel \ + && cp contrib/docker/php.ini /usr/local/etc/php/conf.d/pixelfed.ini \ + && composer install --prefer-source --no-interaction \ + && rm -rf html && ln -s public html + +VOLUME ["/var/www/storage"] + +ENV APP_ENV=production \ + APP_DEBUG=false \ + LOG_CHANNEL=stderr \ + DB_CONNECTION=mysql \ + DB_PORT=3306 \ + DB_HOST=db \ + BROADCAST_DRIVER=log \ + QUEUE_DRIVER=redis \ + HORIZON_PREFIX=horizon-pixelfed \ + REDIS_HOST=redis \ + SESSION_SECURE_COOKIE=true \ + API_BASE="/api/1/" \ + API_SEARCH="/api/search" \ + OPEN_REGISTRATION=true \ + ENFORCE_EMAIL_VERIFICATION=true \ + REMOTE_FOLLOW=false \ + ACTIVITY_PUB=false + +CMD /var/www/contrib/docker/start.sh diff --git a/contrib/docker/Dockerfile.fpm b/contrib/docker/Dockerfile.fpm new file mode 100644 index 000000000..c9ee294a0 --- /dev/null +++ b/contrib/docker/Dockerfile.fpm @@ -0,0 +1,31 @@ +FROM php:7.2.6-fpm-alpine + +ARG COMPOSER_VERSION="1.6.5" +ARG COMPOSER_CHECKSUM="67bebe9df9866a795078bb2cf21798d8b0214f2e0b2fd81f2e907a8ef0be3434" + +RUN apk add --no-cache --virtual .build build-base autoconf imagemagick-dev libtool && \ + apk --no-cache add imagemagick git && \ + docker-php-ext-install pdo_mysql pcntl && \ + pecl install imagick && \ + docker-php-ext-enable imagick pcntl imagick && \ + curl -LsS https://getcomposer.org/download/${COMPOSER_VERSION}/composer.phar -o /tmp/composer.phar && \ + echo "${COMPOSER_CHECKSUM} /tmp/composer.phar" | sha256sum -c - && \ + install -m0755 -o root -g root /tmp/composer.phar /usr/bin/composer.phar && \ + ln -sf /usr/bin/composer.phar /usr/bin/composer && \ + rm /tmp/composer.phar && \ + apk --no-cache del --purge .build + +COPY . /var/www/html/ + +WORKDIR /var/www/html +RUN install -d -m0755 -o www-data -g www-data \ + /var/www/html/storage \ + /var/www/html/storage/framework \ + /var/www/html/storage/logs \ + /var/www/html/storage/framework/sessions \ + /var/www/html/storage/framework/views \ + /var/www/html/storage/framework/cache && \ + composer install --prefer-source --no-interaction + +VOLUME ["/var/www/html"] +ENV PATH="~/.composer/vendor/bin:./vendor/bin:${PATH}" diff --git a/contrib/docker/php.ini b/contrib/docker/php.ini new file mode 100644 index 000000000..7fc73c567 --- /dev/null +++ b/contrib/docker/php.ini @@ -0,0 +1,5 @@ +file_uploads = On +memory_limit = 64M +upload_max_filesize = 64M +post_max_size = 64M +max_execution_time = 600 diff --git a/contrib/docker/start.sh b/contrib/docker/start.sh new file mode 100755 index 000000000..be374a914 --- /dev/null +++ b/contrib/docker/start.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Create the storage tree if needed and fix permissions +cp -r storage.skel/* storage/ +chown -R www-data:www-data storage/ +php artisan storage:link + +# Migrate database if the app was upgraded +php artisan migrate --force + +# Run a worker if it is set as embedded +if [ HORIZON_EMBED = true ]; then + php artisan horizon & +fi + +# Finally run Apache +exec apache2-foreground diff --git a/database/migrations/2018_08_22_022306_update_settings_table.php b/database/migrations/2018_08_22_022306_update_settings_table.php index 500612903..d6d198cc8 100644 --- a/database/migrations/2018_08_22_022306_update_settings_table.php +++ b/database/migrations/2018_08_22_022306_update_settings_table.php @@ -28,9 +28,11 @@ class UpdateSettingsTable extends Migration */ public function down() { - $table->dropColumn('show_profile_followers'); - $table->dropColumn('show_profile_follower_count'); - $table->dropColumn('show_profile_following'); - $table->dropColumn('show_profile_following_count'); + Schema::table('user_settings', function (Blueprint $table) { + $table->dropColumn('show_profile_followers'); + $table->dropColumn('show_profile_follower_count'); + $table->dropColumn('show_profile_following'); + $table->dropColumn('show_profile_following_count'); + }); } } diff --git a/database/migrations/2018_08_27_004653_update_media_table_add_alt_text.php b/database/migrations/2018_08_27_004653_update_media_table_add_alt_text.php new file mode 100644 index 000000000..2071ba3b1 --- /dev/null +++ b/database/migrations/2018_08_27_004653_update_media_table_add_alt_text.php @@ -0,0 +1,44 @@ +string('original_sha256')->nullable()->index()->after('user_id'); + $table->string('optimized_sha256')->nullable()->index()->after('original_sha256'); + $table->string('caption')->nullable()->after('thumbnail_url'); + $table->string('hls_path')->nullable()->after('caption'); + $table->timestamp('hls_transcoded_at')->nullable()->after('processed_at'); + $table->string('key')->nullable(); + $table->json('metadata')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('media', function (Blueprint $table) { + $table->dropColumn('original_sha256'); + $table->dropColumn('optimized_sha256'); + $table->dropColumn('caption'); + $table->dropColumn('hls_path'); + $table->dropColumn('hls_transcoded_at'); + $table->dropColumn('key'); + $table->dropColumn('metadata'); + }); + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 861dc0b9d..4c6e8f6db 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,49 +1,56 @@ --- version: '3' -services: - nginx: - image: nginx:alpine - networks: - - internal - - external - ports: - - 3000:80 - volumes: - - "php-storage:/var/www/html" - - ./contrib/nginx.conf:/etc/nginx/conf.d/default.conf - depends_on: - - php - php: - build: . +# In order to set configuration, please use a .env file in +# your compose project directory (the same directory as your +# docker-compose.yml), and set database options, application +# name, key, and other settings there. +# A list of available settings is available in .env.example +# +# The services should scale properly across a swarm cluster +# if the volumes are properly shared between cluster members. + +services: + + app: + # Uncomment to build a local copy of the image + # build: . image: pixelfed - volumes: - - "php-storage:/var/www/html" - networks: - - internal - environment: - - DB_HOST=mysql - - DB_DATABASE=pixelfed - - DB_USERNAME=${DB_USERNAME:-pixelfed} - - DB_PASSWORD=${DB_PASSWORD:-pixelfed} - - REDIS_HOST=redis - - APP_KEY=${APP_KEY} + # If you have a traefik running, uncomment this to expose Pixelfed + # labels: + # - traefik.enable=true + # - traefik.frontend.rule=Host:your.url + # - traefik.port=80 env_file: - ./.env + volumes: + - "app-storage:/var/www/storage" + networks: + - external + - internal - mysql: + # Uncomment if you set HORIZON_EMBED to false and wish to run a local worker + # worker: + # image: pixelfed + # env_file: + # - ./.env + # volumes: + # - "app-storage:/var/www/storage" + # networks: + # - internal + # command: php artisan horizon + + db: image: mysql:5.7 networks: - internal environment: - MYSQL_DATABASE=pixelfed - - MYSQL_USER=${DB_USERNAME:-pixelfed} - - MYSQL_PASSWORD=${DB_PASSWORD:-pixelfed} - - MYSQL_RANDOM_ROOT_PASSWORD="true" - env_file: - - ./.env + - MYSQL_USER=${DB_USERNAME} + - MYSQL_PASSWORD=${DB_PASSWORD} + - MYSQL_RANDOM_ROOT_PASSWORD=true volumes: - - "mysql-data:/var/lib/mysql" + - "db-data:/var/lib/mysql" redis: image: redis:4-alpine @@ -52,10 +59,11 @@ services: networks: - internal +# Adjust your volume data in order to store data where you wish volumes: redis-data: - mysql-data: - php-storage: + db-data: + app-storage: networks: internal: diff --git a/resources/assets/sass/custom.scss b/resources/assets/sass/custom.scss index 5aa67fb47..90dbb8bbe 100644 --- a/resources/assets/sass/custom.scss +++ b/resources/assets/sass/custom.scss @@ -298,3 +298,13 @@ details summary::-webkit-details-marker { .profile-avatar img { object-fit: cover; } + +.tt-menu { + padding: 0 !important; + border-radius: 0 0 0.25rem 0.25rem !important; +} + +.tt-dataset .alert { + border: 0 !important; + border-radius: 0 !important; +} diff --git a/resources/lang/en/profile.php b/resources/lang/en/profile.php index 9fb9d10db..24278aba8 100644 --- a/resources/lang/en/profile.php +++ b/resources/lang/en/profile.php @@ -6,4 +6,7 @@ return [ 'emptyFollowing' => 'This user is not following anyone yet!', 'emptySaved' => 'You haven’t saved any post yet!', 'savedWarning' => 'Only you can see what you’ve saved', + 'privateProfileWarning' => 'This Account is Private', + 'alreadyFollow' => 'Already follow :username?', + 'loginToSeeProfile' => 'to see their photos and videos.', ]; diff --git a/resources/views/account/verify_email.blade.php b/resources/views/account/verify_email.blade.php index 99ae26f3c..f79cdfc5f 100644 --- a/resources/views/account/verify_email.blade.php +++ b/resources/views/account/verify_email.blade.php @@ -5,7 +5,12 @@
@if (session('status'))
- {{ session('status') }} +

{{ session('status') }}

+
+ @endif + @if (session('error')) +
+

{{ session('error') }}

@endif
diff --git a/resources/views/admin/reports/home.blade.php b/resources/views/admin/reports/home.blade.php new file mode 100644 index 000000000..bc1d7228d --- /dev/null +++ b/resources/views/admin/reports/home.blade.php @@ -0,0 +1,57 @@ +@extends('admin.partial.template') + +@section('section') +
+

Reports

+
+ +
+ + + + + + + + + + + + + + @foreach($reports as $report) + + + + + + @if(!$report->admin_seen) + + @else + + @endif + + + @endforeach + +
#ReporterTypeReportedStatusCreated
+ + {{$report->id}} + + {{$report->reporter->username}}{{$report->type}}{{str_limit($report->reported()->url(), 25)}}UnresolvedResolved{{$report->created_at->diffForHumans(null, true, true, true)}}
+
+ {{$reports->links()}} +
+@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/admin/reports/show.blade.php b/resources/views/admin/reports/show.blade.php new file mode 100644 index 000000000..e199d00d6 --- /dev/null +++ b/resources/views/admin/reports/show.blade.php @@ -0,0 +1,167 @@ +@extends('admin.partial.template') + +@section('section') +
+

Report #{{$report->id}} - {{ucfirst($report->type)}}

+
+ +
+
+
Reported: {{$report->reported()->url()}}
+
Reported by: {{$report->reporter->username}} admin
+

+ Message: + {{$report->message ?? 'No message provided.'}} +

+ + @if(!$report->admin_seen) + Ignore + {{-- Request Mod Feedback --}} + Add CW + Unlist/Hide + Delete + Shadowban User + Ban User + @else +

Resolved {{$report->admin_seen->diffForHumans()}}

+ @endif +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+ Reporter +
+
    +
  • Joined {{$report->reporter->created_at->diffForHumans()}}
  • +
  • Total Reports: {{App\Report::whereProfileId($report->reporter->id)->count()}}
  • +
  • Total Reported: {{App\Report::whereReportedProfileId($report->reporter->id)->count()}}
  • +
+
+
+
+
+
+ Reported +
+
    +
  • Joined {{$report->reportedUser->created_at->diffForHumans()}}
  • +
  • Total Reports: {{App\Report::whereProfileId($report->reportedUser->id)->count()}}
  • +
  • Total Reported: {{App\Report::whereReportedProfileId($report->reportedUser->id)->count()}}
  • +
+
+
+
+
+
+
+
+ +{{--
+
+
+
+ +
+
+
+
+
+

admin ignored this report. 2m

+
+
+

admin ignored this report. 2m

+
+
+

admin ignored this report. 2m

+
+
+
+
+
--}} + + +{{--
+
+
+
+ +
+
+
+
+
+
+
+
+ [username]: {{str_limit('Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod.', 150)}} 2m +
+
+
+
+
+
+ me: {{str_limit('Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod.', 150)}} 2m +
+
+
+
+
+
+ me: {{str_limit('Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod.', 150)}} 2m +
+
+
+
+
+ +
+
+
--}} +@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/admin/settings/backups.blade.php b/resources/views/admin/settings/backups.blade.php new file mode 100644 index 000000000..7aa6ceba4 --- /dev/null +++ b/resources/views/admin/settings/backups.blade.php @@ -0,0 +1,74 @@ +@extends('admin.partial.template') + +@section('section') +
+

Site Backups

+
+
+
+
+
+
Settings
+
+
+
+ +
+ + +
+ + Enable automated backups with your own strategy. + +
+
+ + + + Select the backup frequency. + +
+
+ + + + You can use local, S3, or any S3 compatible object storage API to store backups. + +
+
+
+
+
+
+
+
Current Backups
+
+ @foreach($files as $file) + @if($file->isFile()) +
  • +

    {{$file->getFilename()}}

    +

    + + Size: {{App\Util\Lexer\PrettyNumber::convert($file->getSize())}} + + + Created: {{\Carbon\Carbon::createFromTimestamp($file->getMTime())->diffForHumans()}}

    + +

    +
  • + @endif + @endforeach +
    +
    + +
    +
    +@endsection \ No newline at end of file diff --git a/resources/views/admin/settings/maintenance.blade.php b/resources/views/admin/settings/maintenance.blade.php new file mode 100644 index 000000000..9182e94d0 --- /dev/null +++ b/resources/views/admin/settings/maintenance.blade.php @@ -0,0 +1,9 @@ +@extends('admin.partial.template') + +@section('section') +
    +

    Maintenance

    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/admin/settings/storage.blade.php b/resources/views/admin/settings/storage.blade.php new file mode 100644 index 000000000..294c84e3d --- /dev/null +++ b/resources/views/admin/settings/storage.blade.php @@ -0,0 +1,30 @@ +@extends('admin.partial.template') + +@section('section') +
    +

    Storage

    +
    +
    + +
    +
    +
    +
    +
    +
    + + Used: {{$storage->prettyTotal}} + + + {{$storage->percentUsed}}% Used + + + Free: {{$storage->prettyFree}} + +
    +
    + +
    +@endsection \ No newline at end of file diff --git a/resources/views/admin/settings/system.blade.php b/resources/views/admin/settings/system.blade.php new file mode 100644 index 000000000..b64f02a07 --- /dev/null +++ b/resources/views/admin/settings/system.blade.php @@ -0,0 +1,39 @@ +@extends('admin.partial.template') + +@section('section') +
    +

    System

    +
    +
    +
    +
    +
    +
    +

    {{config('pixelfed.version')}}

    +
    + +
    + +
    +
    +

    {{DB::select( DB::raw("select version()") )[0]->{'version()'} }}

    +
    + +
    +
    +
    +
    +
    +

    {{phpversion()}}

    +
    + +
    +{{--
    +
    +

    +
    + +
    --}} +
    +
    +@endsection \ No newline at end of file diff --git a/resources/views/layouts/anon.blade.php b/resources/views/layouts/anon.blade.php new file mode 100644 index 000000000..4621b821c --- /dev/null +++ b/resources/views/layouts/anon.blade.php @@ -0,0 +1,40 @@ + + + + + + + + + + + + + {{ $title or config('app.name', 'Laravel') }} + + @if(isset($title)) + + + + @endif + + @stack('meta') + + + + + + + + @stack('styles') + + + @include('layouts.partial.noauthnav') +
    + @yield('content') +
    + @include('layouts.partial.footer') + + @stack('scripts') + + diff --git a/resources/views/layouts/partial/noauthnav.blade.php b/resources/views/layouts/partial/noauthnav.blade.php new file mode 100644 index 000000000..797f1362e --- /dev/null +++ b/resources/views/layouts/partial/noauthnav.blade.php @@ -0,0 +1,8 @@ + diff --git a/resources/views/profile/partial/private-info.blade.php b/resources/views/profile/partial/private-info.blade.php new file mode 100644 index 000000000..1e69755f1 --- /dev/null +++ b/resources/views/profile/partial/private-info.blade.php @@ -0,0 +1,32 @@ +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + {{$user->username}} +
    +
    +
    + {{$user->statuses()->whereNull('reblog_of_id')->whereNull('in_reply_to_id')->count()}} + Posts +
    +
    +

    + {{$user->name}} + @if($user->remote_url) + REMOTE PROFILE + @endif +

    +

    {{$user->bio}}

    +

    {{str_limit($user->website, 30)}}

    +
    +
    +
    +
    +
    diff --git a/resources/views/profile/partial/user-info.blade.php b/resources/views/profile/partial/user-info.blade.php index 75326885f..0f51a8e4b 100644 --- a/resources/views/profile/partial/user-info.blade.php +++ b/resources/views/profile/partial/user-info.blade.php @@ -57,18 +57,22 @@ Posts
    + @if($settings->show_profile_follower_count)
    {{$user->followerCount(true)}} Followers
    + @endif + @if($settings->show_profile_following_count)
    {{$user->followingCount(true)}} Following
    + @endif

    {{$user->name}} diff --git a/resources/views/profile/private.blade.php b/resources/views/profile/private.blade.php new file mode 100644 index 000000000..dda823e33 --- /dev/null +++ b/resources/views/profile/private.blade.php @@ -0,0 +1,33 @@ +@extends('layouts.app',['title' => $user->username . " on " . config('app.name')]) + +@section('content') + +@include('profile.partial.private-info') + +

    +
    +
    +
    +

    + {{__('profile.privateProfileWarning')}} +

    + + @if(Auth::check()) +

    {{ __('profile.alreadyFollow', ['username'=>$user->username])}}

    +

    {{__('Log in')}}

    +

    {{__('profile.loginToSeeProfile')}}

    + @endif +
    +
    +
    +
    + +@endsection + +@push('meta') + + +@if($user->remote_url) + +@endif +@endpush \ No newline at end of file diff --git a/resources/views/profile/show.blade.php b/resources/views/profile/show.blade.php index fa502ae1a..885d2388a 100644 --- a/resources/views/profile/show.blade.php +++ b/resources/views/profile/show.blade.php @@ -74,6 +74,7 @@ @push('meta') + @if(false == $settings->crawlable || $user->remote_url) @endif diff --git a/resources/views/report/abusive/comment.blade.php b/resources/views/report/abusive/comment.blade.php new file mode 100644 index 000000000..aa7c70678 --- /dev/null +++ b/resources/views/report/abusive/comment.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('content') + +
    +
    +
    +
    + Report Abusive/Harmful Comment +
    +
    +
    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    + Learn more + about our reporting guidelines and policy.

    +
    +
    +
    +
    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/report/abusive/post.blade.php b/resources/views/report/abusive/post.blade.php new file mode 100644 index 000000000..9957a3802 --- /dev/null +++ b/resources/views/report/abusive/post.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('content') + +
    +
    +
    +
    + Report Abusive/Harmful Post +
    +
    +
    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    + Learn more + about our reporting guidelines and policy.

    +
    +
    +
    +
    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/report/abusive/profile.blade.php b/resources/views/report/abusive/profile.blade.php new file mode 100644 index 000000000..6b9ca4991 --- /dev/null +++ b/resources/views/report/abusive/profile.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('content') + +
    +
    +
    +
    + Report Abusive/Harmful Profile +
    +
    +
    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    + Learn more + about our reporting guidelines and policy.

    +
    +
    +
    +
    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/report/form.blade.php b/resources/views/report/form.blade.php index ec7320aad..9718b53a0 100644 --- a/resources/views/report/form.blade.php +++ b/resources/views/report/form.blade.php @@ -5,41 +5,90 @@
    -
    -
    -

    This feature is not yet ready for production. Please try again later.

    -
    -
    - -
    -
    +
    +
    Report
    - diff --git a/resources/views/report/sensitive/comment.blade.php b/resources/views/report/sensitive/comment.blade.php new file mode 100644 index 000000000..5313098ba --- /dev/null +++ b/resources/views/report/sensitive/comment.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('content') + +
    +
    +
    +
    + Report Sensitive Comment +
    +
    +
    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    + Learn more + about our reporting guidelines and policy.

    +
    +
    +
    +
    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/report/sensitive/post.blade.php b/resources/views/report/sensitive/post.blade.php new file mode 100644 index 000000000..bb6e47e17 --- /dev/null +++ b/resources/views/report/sensitive/post.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('content') + +
    +
    +
    +
    + Report Sensitive Post +
    +
    +
    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    + Learn more + about our reporting guidelines and policy.

    +
    +
    +
    +
    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/report/sensitive/profile.blade.php b/resources/views/report/sensitive/profile.blade.php new file mode 100644 index 000000000..c6b00befd --- /dev/null +++ b/resources/views/report/sensitive/profile.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') + +@section('content') + +
    +
    +
    +
    + Report Sensitive Profile +
    +
    +
    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +

    + Learn more + about our reporting guidelines and policy.

    +
    +
    +
    +
    +
    +
    + +@endsection \ No newline at end of file diff --git a/resources/views/report/spam.blade.php b/resources/views/report/spam.blade.php index aff2fb3e8..50ce6e5eb 100644 --- a/resources/views/report/spam.blade.php +++ b/resources/views/report/spam.blade.php @@ -13,21 +13,30 @@

    Please select one of the following options.

    -
    + @switch(request()->query('type')) + + @case('comment') + -
    + @break + @case('post') + -
    + @break + @case('user') + + @break + @endswitch
    -
    -

    Please select one of the following options.

    -
    -
    -

    - This comment contains spam -

    +
    +
    + @csrf + + + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    - - -
    + +

    Learn more about our reporting guidelines and policy.

    diff --git a/resources/views/report/spam/profile.blade.php b/resources/views/report/spam/profile.blade.php index 9e4a36e6f..6ee85c67d 100644 --- a/resources/views/report/spam/profile.blade.php +++ b/resources/views/report/spam/profile.blade.php @@ -28,7 +28,7 @@ This users profile contains spam

    -
    +

    Learn more about our reporting guidelines and policy.

    diff --git a/resources/views/settings/home.blade.php b/resources/views/settings/home.blade.php index 4c43b306d..18f78e3f1 100644 --- a/resources/views/settings/home.blade.php +++ b/resources/views/settings/home.blade.php @@ -39,6 +39,9 @@
    + + Max length: {{config('pixelfed.max_bio_length')}} characters. +
    @@ -134,4 +137,4 @@ }); }); -@endpush \ No newline at end of file +@endpush diff --git a/resources/views/status/edit.blade.php b/resources/views/status/edit.blade.php new file mode 100644 index 000000000..ffb23cb37 --- /dev/null +++ b/resources/views/status/edit.blade.php @@ -0,0 +1,91 @@ +@extends('layouts.app') + +@section('content') + +
    +
    + +
    +
    + Edit Status + Back to post +
    +
    + @csrf +
    + +
    + is_nsfw==true?'checked=""':''}} disabled=""> + +
    +
    +
    +
    + + @foreach($status->media()->orderBy('order')->get() as $media) +
    +
    + Media #{{$media->order}} +
    +
    +
    + @csrf + +
    + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +

    Last Updated: {{$media->updated_at->diffForHumans()}}

    + +
    +
    +
    +
    +
    + @endforeach + +
    +
    +@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/status/show/album.blade.php b/resources/views/status/show/album.blade.php new file mode 100644 index 000000000..4dea9e76c --- /dev/null +++ b/resources/views/status/show/album.blade.php @@ -0,0 +1,65 @@ +@extends('layouts.app',['title' => $user->username . " posted a photo: " . $status->likes_count . " likes, " . $status->comments_count . " comments" ]) + +@section('content') + +
    +
    +
    + +
    + @if($status->is_nsfw) +
    + +

    CW / NSFW / Hidden Media

    +

    (click to show)

    +
    + @endif + + @if($status->is_nsfw) +
    + @endif +
    + @include('status.show.sidebar') +
    +
    +
    + +@endsection + +@push('meta') + + + +@endpush diff --git a/resources/views/status/show/photo.blade.php b/resources/views/status/show/photo.blade.php new file mode 100644 index 000000000..dba5bcb7a --- /dev/null +++ b/resources/views/status/show/photo.blade.php @@ -0,0 +1,46 @@ +@extends('layouts.app',['title' => $user->username . " posted a photo: " . $status->likes_count . " likes, " . $status->comments_count . " comments" ]) + +@section('content') + +
    +
    +
    + +
    + @if($status->is_nsfw && $status->media_count == 1) +
    + +

    CW / NSFW / Hidden Media

    +

    (click to show)

    +
    + + + +
    + @elseif(!$status->is_nsfw && $status->media_count == 1) +
    + +
    + @endif +
    + @include('status.show.sidebar') +
    +
    +
    + +@endsection + +@push('meta') + + + +@endpush diff --git a/resources/views/status/show/sidebar.blade.php b/resources/views/status/show/sidebar.blade.php new file mode 100644 index 000000000..0c245375c --- /dev/null +++ b/resources/views/status/show/sidebar.blade.php @@ -0,0 +1,101 @@ +
    +
    + +
    + +
    +
    + {{$user->username}} +
    +
    +
    + +
    +
    +
    +
    +
    +

    + {{$status->profile->username}} + {!! $status->rendered ?? e($status->caption) !!} +

    +

    View all comments

    +
    + @foreach($replies as $item) +

    + {{ str_limit($item->profile->username, 15)}} + {!! $item->rendered ?? e($item->caption) !!} {{$item->created_at->diffForHumans(null, true, true ,true)}} +

    + @endforeach +
    +
    +
    +
    +
    + @if(Auth::check()) +
    + @csrf + + +
    +

    + + + @endif + +
    + @csrf + + +
    +
    +
    + + +
    +
    + +
    \ No newline at end of file diff --git a/resources/views/status/show/video.blade.php b/resources/views/status/show/video.blade.php new file mode 100644 index 000000000..5babc6f68 --- /dev/null +++ b/resources/views/status/show/video.blade.php @@ -0,0 +1,50 @@ +@extends('layouts.app',['title' => $user->username . " posted a photo: " . $status->likes_count . " likes, " . $status->comments_count . " comments" ]) + +@section('content') + +
    +
    +
    + +
    + @if($status->is_nsfw && $status->media_count == 1) +
    + +

    CW / NSFW / Hidden Media

    +

    (click to show)

    +
    +
    + +
    +
    + @elseif(!$status->is_nsfw && $status->media_count == 1) +
    + +
    + @endif +
    + @include('status.show.sidebar') +
    +
    +
    + +@endsection + +@push('meta') + + + +@endpush diff --git a/routes/web.php b/routes/web.php index 41625e378..9fa4f9f25 100644 --- a/routes/web.php +++ b/routes/web.php @@ -67,11 +67,18 @@ Route::domain(config('pixelfed.domain.app'))->middleware('validemail')->group(fu Route::group(['prefix' => 'report'], function() { Route::get('/', 'ReportController@showForm')->name('report.form'); + Route::post('/', 'ReportController@formStore'); Route::get('not-interested', 'ReportController@notInterestedForm')->name('report.not-interested'); Route::get('spam', 'ReportController@spamForm')->name('report.spam'); Route::get('spam/comment', 'ReportController@spamCommentForm')->name('report.spam.comment'); Route::get('spam/post', 'ReportController@spamPostForm')->name('report.spam.post'); Route::get('spam/profile', 'ReportController@spamProfileForm')->name('report.spam.profile'); + Route::get('sensitive/comment', 'ReportController@sensitiveCommentForm')->name('report.sensitive.comment'); + Route::get('sensitive/post', 'ReportController@sensitivePostForm')->name('report.sensitive.post'); + Route::get('sensitive/profile', 'ReportController@sensitiveProfileForm')->name('report.sensitive.profile'); + Route::get('abusive/comment', 'ReportController@abusiveCommentForm')->name('report.abusive.comment'); + Route::get('abusive/post', 'ReportController@abusivePostForm')->name('report.abusive.post'); + Route::get('abusive/profile', 'ReportController@abusiveProfileForm')->name('report.abusive.profile'); }); }); @@ -128,6 +135,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware('validemail')->group(fu Route::get('p/{username}/{id}/c/{cid}', 'CommentController@show'); Route::get('p/{username}/{id}/c', 'CommentController@showAll'); + Route::get('p/{username}/{id}/edit', 'StatusController@edit'); + Route::post('p/{username}/{id}/edit', 'StatusController@editStore'); Route::get('p/{username}/{id}', 'StatusController@show'); Route::get('{username}/saved', 'ProfileController@savedBookmarks'); Route::get('{username}/followers', 'ProfileController@followers'); diff --git a/tests/Unit/CryptoTest.php b/tests/Unit/CryptoTest.php new file mode 100644 index 000000000..15ecac713 --- /dev/null +++ b/tests/Unit/CryptoTest.php @@ -0,0 +1,31 @@ +assertTrue(class_exists('\phpseclib\Crypt\RSA')); + } + + public function testRSASigning() + { + $rsa = new \phpseclib\Crypt\RSA(); + extract($rsa->createKey()); + $rsa->loadKey($privatekey); + $plaintext = 'pixelfed rsa test'; + $signature = $rsa->sign($plaintext); + $rsa->loadKey($publickey); + $this->assertTrue($rsa->verify($plaintext, $signature)); + } +}