diff --git a/.env.docker b/.env.docker
index a15e15431..8367c0032 100644
--- a/.env.docker
+++ b/.env.docker
@@ -67,7 +67,7 @@ ADMIN_DOMAIN="${APP_DOMAIN}"
# @default "false"
# @see https://docs.pixelfed.org/technical-documentation/config/#config_cache
# @dottie/validate required,boolean
-ENABLE_CONFIG_CACHE="false"
+ENABLE_CONFIG_CACHE="true"
# Enable/disable new local account registrations.
#
diff --git a/.env.example b/.env.example
index d4d7228d1..79ce65337 100644
--- a/.env.example
+++ b/.env.example
@@ -8,6 +8,7 @@ OPEN_REGISTRATION="false"
ENFORCE_EMAIL_VERIFICATION="false"
PF_MAX_USERS="1000"
OAUTH_ENABLED="true"
+ENABLE_CONFIG_CACHE=true
# Media Configuration
PF_OPTIMIZE_IMAGES="true"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e75ba0c8..b532a454f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,19 @@
# Release Notes
-## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.11.13...dev)
+## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.12.1...dev)
+
+### Updates
+- Update DirectMessageController, add 72 hour delay for new accounts before they can send a DM ([61d105fd](https://github.com/pixelfed/pixelfed/commit/61d105fd))
+- Update AdminCuratedRegisterController, increase message length from 1000 to 3000 ([9a5e3471](https://github.com/pixelfed/pixelfed/commit/))
+- ([](https://github.com/pixelfed/pixelfed/commit/9a5e3471))
+
+## [v0.12.1 (2024-05-07)](https://github.com/pixelfed/pixelfed/compare/v0.12.0...v0.12.1)
+
+### Updates
+- Update ApiV1Dot1Controller, fix in app registration bug that prevents proper auth flow due to missing oauth scopes ([cbf996c9](https://github.com/pixelfed/pixelfed/commit/cbf996c9))
+- Update ConfigCacheService, fix database race condition and fallback to file config and enable by default ([60a62b59](https://github.com/pixelfed/pixelfed/commit/60a62b59))
+
+## [v0.12.0 (2024-04-29)](https://github.com/pixelfed/pixelfed/compare/v0.11.13...v0.12.0)
### Updates
@@ -66,7 +79,11 @@
- Update UnfollowPipeline, fix follower count cache bug ([6bdf73de](https://github.com/pixelfed/pixelfed/commit/6bdf73de))
- Update VideoPresenter component, add webkit-playsinline attribute to video element to prevent the full screen video player ([ad032916](https://github.com/pixelfed/pixelfed/commit/ad032916))
- Update VideoPlayer component, add playsinline attribute to video element ([8af23607](https://github.com/pixelfed/pixelfed/commit/8af23607))
-- ([](https://github.com/pixelfed/pixelfed/commit/))
+- Update StatusController, refactor status embeds ([9a7acc12](https://github.com/pixelfed/pixelfed/commit/9a7acc12))
+- Update ProfileController, refactor profile embeds ([8b8b1ffc](https://github.com/pixelfed/pixelfed/commit/8b8b1ffc))
+- Update profile embed view, fix height bug ([65166570](https://github.com/pixelfed/pixelfed/commit/65166570))
+- Update CustomEmojiService, only return local emoji ([7f8bba44](https://github.com/pixelfed/pixelfed/commit/7f8bba44))
+- Update Like model, increase max likes per day from 500 to 1500 ([4223119f](https://github.com/pixelfed/pixelfed/commit/4223119f))
## [v0.11.13 (2024-03-05)](https://github.com/pixelfed/pixelfed/compare/v0.11.12...v0.11.13)
diff --git a/app/Http/Controllers/AdminCuratedRegisterController.php b/app/Http/Controllers/AdminCuratedRegisterController.php
index 7b25ac369..4e1d0eec9 100644
--- a/app/Http/Controllers/AdminCuratedRegisterController.php
+++ b/app/Http/Controllers/AdminCuratedRegisterController.php
@@ -174,7 +174,7 @@ class AdminCuratedRegisterController extends Controller
public function apiMessageSendStore(Request $request, $id)
{
$this->validate($request, [
- 'message' => 'required|string|min:5|max:1000',
+ 'message' => 'required|string|min:5|max:3000',
]);
$record = CuratedRegister::findOrFail($id);
abort_if($record->email_verified_at === null, 400, 'Cannot message an unverified email');
diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php
index 6d051866b..59fb1c93e 100644
--- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php
+++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php
@@ -2,914 +2,919 @@
namespace App\Http\Controllers\Api;
-use Cache;
-use DB;
-use App\Http\Controllers\Controller;
-use Illuminate\Http\Request;
-use League\Fractal;
-use League\Fractal\Serializer\ArraySerializer;
-use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use App\AccountLog;
use App\EmailVerification;
-use App\Follower;
+use App\Http\Controllers\Controller;
+use App\Http\Resources\StatusStateless;
+use App\Jobs\ReportPipeline\ReportNotifyAdminViaEmail;
+use App\Jobs\StatusPipeline\RemoteStatusDelete;
+use App\Jobs\StatusPipeline\StatusDelete;
+use App\Mail\ConfirmAppEmail;
+use App\Mail\PasswordChange;
use App\Place;
-use App\Status;
-use App\Report;
use App\Profile;
+use App\Report;
+use App\Services\AccountService;
+use App\Services\BouncerService;
+use App\Services\EmailService;
+use App\Services\FollowerService;
+use App\Services\NetworkTimelineService;
+use App\Services\ProfileStatusService;
+use App\Services\PublicTimelineService;
+use App\Services\StatusService;
+use App\Status;
use App\StatusArchived;
use App\User;
use App\UserSetting;
-use App\Services\AccountService;
-use App\Services\FollowerService;
-use App\Services\StatusService;
-use App\Services\ProfileStatusService;
-use App\Services\LikeService;
-use App\Services\ReblogService;
-use App\Services\PublicTimelineService;
-use App\Services\NetworkTimelineService;
use App\Util\Lexer\RestrictedNames;
-use App\Services\BouncerService;
-use App\Services\EmailService;
-use Illuminate\Support\Str;
+use Cache;
+use DB;
+use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
-use Jenssegers\Agent\Agent;
-use Mail;
-use App\Mail\PasswordChange;
-use App\Mail\ConfirmAppEmail;
-use App\Http\Resources\StatusStateless;
-use App\Jobs\StatusPipeline\StatusDelete;
-use App\Jobs\StatusPipeline\RemoteStatusDelete;
-use App\Jobs\ReportPipeline\ReportNotifyAdminViaEmail;
use Illuminate\Support\Facades\RateLimiter;
+use Illuminate\Support\Str;
+use Jenssegers\Agent\Agent;
+use League\Fractal;
+use League\Fractal\Serializer\ArraySerializer;
+use Mail;
class ApiV1Dot1Controller extends Controller
{
- protected $fractal;
-
- public function __construct()
- {
- $this->fractal = new Fractal\Manager();
- $this->fractal->setSerializer(new ArraySerializer());
- }
-
- public function json($res, $code = 200, $headers = [])
- {
- return response()->json($res, $code, $headers, JSON_UNESCAPED_SLASHES);
- }
-
- public function error($msg, $code = 400, $extra = [], $headers = [])
- {
- $res = [
- "msg" => $msg,
- "code" => $code
- ];
- return response()->json(array_merge($res, $extra), $code, $headers, JSON_UNESCAPED_SLASHES);
- }
-
- public function report(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('write'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $report_type = $request->input('report_type');
- $object_id = $request->input('object_id');
- $object_type = $request->input('object_type');
-
- $types = [
- 'spam',
- 'sensitive',
- 'abusive',
- 'underage',
- 'violence',
- 'copyright',
- 'impersonation',
- 'scam',
- 'terrorism'
- ];
-
- if (!$report_type || !$object_id || !$object_type) {
- return $this->error("Invalid or missing parameters", 400, ["error_code" => "ERROR_INVALID_PARAMS"]);
- }
-
- if (!in_array($report_type, $types)) {
- return $this->error("Invalid report type", 400, ["error_code" => "ERROR_TYPE_INVALID"]);
- }
-
- if ($object_type === "user" && $object_id == $user->profile_id) {
- return $this->error("Cannot self report", 400, ["error_code" => "ERROR_NO_SELF_REPORTS"]);
- }
-
- $rpid = null;
-
- switch ($object_type) {
- case 'post':
- $object = Status::find($object_id);
- if (!$object) {
- return $this->error("Invalid object id", 400, ["error_code" => "ERROR_INVALID_OBJECT_ID"]);
- }
- $object_type = 'App\Status';
- $exists = Report::whereUserId($user->id)
- ->whereObjectId($object->id)
- ->whereObjectType('App\Status')
- ->count();
-
- $rpid = $object->profile_id;
- break;
-
- case 'user':
- $object = Profile::find($object_id);
- if (!$object) {
- return $this->error("Invalid object id", 400, ["error_code" => "ERROR_INVALID_OBJECT_ID"]);
- }
- $object_type = 'App\Profile';
- $exists = Report::whereUserId($user->id)
- ->whereObjectId($object->id)
- ->whereObjectType('App\Profile')
- ->count();
- $rpid = $object->id;
- break;
-
- default:
- return $this->error("Invalid report type", 400, ["error_code" => "ERROR_REPORT_OBJECT_TYPE_INVALID"]);
- break;
- }
-
- if ($exists !== 0) {
- return $this->error("Duplicate report", 400, ["error_code" => "ERROR_REPORT_DUPLICATE"]);
- }
-
- if ($object->profile_id == $user->profile_id) {
- return $this->error("Cannot self report", 400, ["error_code" => "ERROR_NO_SELF_REPORTS"]);
- }
-
- $report = new Report;
- $report->profile_id = $user->profile_id;
- $report->user_id = $user->id;
- $report->object_id = $object->id;
- $report->object_type = $object_type;
- $report->reported_profile_id = $rpid;
- $report->type = $report_type;
- $report->save();
-
- if(config('instance.reports.email.enabled')) {
- ReportNotifyAdminViaEmail::dispatch($report)->onQueue('default');
- }
-
- $res = [
- "msg" => "Successfully sent report",
- "code" => 200
- ];
- return $this->json($res);
- }
-
- /**
- * DELETE /api/v1.1/accounts/avatar
- *
- * @return \App\Transformer\Api\AccountTransformer
- */
- public function deleteAvatar(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('write'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $avatar = $user->profile->avatar;
-
- if( $avatar->media_path == 'public/avatars/default.png' ||
- $avatar->media_path == 'public/avatars/default.jpg'
- ) {
- return AccountService::get($user->profile_id);
- }
-
- if(is_file(storage_path('app/' . $avatar->media_path))) {
- @unlink(storage_path('app/' . $avatar->media_path));
- }
-
- $avatar->media_path = 'public/avatars/default.jpg';
- $avatar->change_count = $avatar->change_count + 1;
- $avatar->save();
-
- Cache::forget('avatar:' . $user->profile_id);
- Cache::forget("avatar:{$user->profile_id}");
- Cache::forget('user:account:id:'.$user->id);
- AccountService::del($user->profile_id);
-
- return AccountService::get($user->profile_id);
- }
-
- /**
- * GET /api/v1.1/accounts/{id}/posts
- *
- * @return \App\Transformer\Api\StatusTransformer
- */
- public function accountPosts(Request $request, $id)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $account = AccountService::get($id);
-
- if(!$account || $account['username'] !== $request->input('username')) {
- return $this->json([]);
- }
-
- $posts = ProfileStatusService::get($id);
-
- if(!$posts) {
- return $this->json([]);
- }
-
- $res = collect($posts)
- ->map(function($id) {
- return StatusService::get($id);
- })
- ->filter(function($post) {
- return $post && isset($post['account']);
- })
- ->toArray();
-
- return $this->json($res);
- }
-
- /**
- * POST /api/v1.1/accounts/change-password
- *
- * @return \App\Transformer\Api\AccountTransformer
- */
- public function accountChangePassword(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('write'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $this->validate($request, [
- 'current_password' => 'bail|required|current_password',
- 'new_password' => 'required|min:' . config('pixelfed.min_password_length', 8),
- 'confirm_password' => 'required|same:new_password'
- ],[
- 'current_password' => 'The password you entered is incorrect'
- ]);
-
- $user->password = bcrypt($request->input('new_password'));
- $user->save();
-
- $log = new AccountLog;
- $log->user_id = $user->id;
- $log->item_id = $user->id;
- $log->item_type = 'App\User';
- $log->action = 'account.edit.password';
- $log->message = 'Password changed';
- $log->link = null;
- $log->ip_address = $request->ip();
- $log->user_agent = $request->userAgent();
- $log->save();
-
- Mail::to($request->user())->send(new PasswordChange($user));
-
- return $this->json(AccountService::get($user->profile_id));
- }
-
- /**
- * GET /api/v1.1/accounts/login-activity
- *
- * @return array
- */
- public function accountLoginActivity(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
- $agent = new Agent();
- $currentIp = $request->ip();
-
- $activity = AccountLog::whereUserId($user->id)
- ->whereAction('auth.login')
- ->orderBy('created_at', 'desc')
- ->groupBy('ip_address')
- ->limit(10)
- ->get()
- ->map(function($item) use($agent, $currentIp) {
- $agent->setUserAgent($item->user_agent);
- return [
- 'id' => $item->id,
- 'action' => $item->action,
- 'ip' => $item->ip_address,
- 'ip_current' => $item->ip_address === $currentIp,
- 'is_mobile' => $agent->isMobile(),
- 'device' => $agent->device(),
- 'browser' => $agent->browser(),
- 'platform' => $agent->platform(),
- 'created_at' => $item->created_at->format('c')
- ];
- });
-
- return $this->json($activity);
- }
-
- /**
- * GET /api/v1.1/accounts/two-factor
- *
- * @return array
- */
- public function accountTwoFactor(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $res = [
- 'active' => (bool) $user->{'2fa_enabled'},
- 'setup_at' => $user->{'2fa_setup_at'}
- ];
- return $this->json($res);
- }
-
- /**
- * GET /api/v1.1/accounts/emails-from-pixelfed
- *
- * @return array
- */
- public function accountEmailsFromPixelfed(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
- $from = config('mail.from.address');
-
- $emailVerifications = EmailVerification::whereUserId($user->id)
- ->orderByDesc('id')
- ->where('created_at', '>', now()->subDays(14))
- ->limit(10)
- ->get()
- ->map(function($mail) use($user, $from) {
- return [
- 'type' => 'Email Verification',
- 'subject' => 'Confirm Email',
- 'to_address' => $user->email,
- 'from_address' => $from,
- 'created_at' => str_replace('@', 'at', $mail->created_at->format('M j, Y @ g:i:s A'))
- ];
- })
- ->toArray();
-
- $passwordResets = DB::table('password_resets')
- ->whereEmail($user->email)
- ->where('created_at', '>', now()->subDays(14))
- ->orderByDesc('created_at')
- ->limit(10)
- ->get()
- ->map(function($mail) use($user, $from) {
- return [
- 'type' => 'Password Reset',
- 'subject' => 'Reset Password Notification',
- 'to_address' => $user->email,
- 'from_address' => $from,
- 'created_at' => str_replace('@', 'at', now()->parse($mail->created_at)->format('M j, Y @ g:i:s A'))
- ];
- })
- ->toArray();
-
- $passwordChanges = AccountLog::whereUserId($user->id)
- ->whereAction('account.edit.password')
- ->where('created_at', '>', now()->subDays(14))
- ->orderByDesc('created_at')
- ->limit(10)
- ->get()
- ->map(function($mail) use($user, $from) {
- return [
- 'type' => 'Password Change',
- 'subject' => 'Password Change',
- 'to_address' => $user->email,
- 'from_address' => $from,
- 'created_at' => str_replace('@', 'at', now()->parse($mail->created_at)->format('M j, Y @ g:i:s A'))
- ];
- })
- ->toArray();
-
- $res = collect([])
- ->merge($emailVerifications)
- ->merge($passwordResets)
- ->merge($passwordChanges)
- ->sortByDesc('created_at')
- ->values();
-
- return $this->json($res);
- }
-
- /**
- * GET /api/v1.1/accounts/apps-and-applications
- *
- * @return array
- */
- public function accountApps(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- $user = $request->user();
- abort_if($user->status != null, 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $res = $user->tokens->sortByDesc('created_at')->take(10)->map(function($token, $key) use($request) {
- return [
- 'id' => $token->id,
- 'current_session' => $request->user()->token()->id == $token->id,
- 'name' => $token->client->name,
- 'scopes' => $token->scopes,
- 'revoked' => $token->revoked,
- 'created_at' => str_replace('@', 'at', now()->parse($token->created_at)->format('M j, Y @ g:i:s A')),
- 'expires_at' => str_replace('@', 'at', now()->parse($token->expires_at)->format('M j, Y @ g:i:s A'))
- ];
- });
-
- return $this->json($res);
- }
-
- public function inAppRegistrationPreFlightCheck(Request $request)
- {
- return [
- 'open' => (bool) config_cache('pixelfed.open_registration'),
- 'iara' => (bool) config_cache('pixelfed.allow_app_registration'),
- ];
- }
-
- public function inAppRegistration(Request $request)
- {
- abort_if($request->user(), 404);
- abort_unless((bool) config_cache('pixelfed.open_registration'), 404);
- abort_unless((bool) config_cache('pixelfed.allow_app_registration'), 404);
- abort_unless($request->hasHeader('X-PIXELFED-APP'), 403);
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $rl = RateLimiter::attempt('pf:apiv1.1:iar:'.$request->ip(), config('pixelfed.app_registration_rate_limit_attempts', 3), function(){}, config('pixelfed.app_registration_rate_limit_decay', 1800));
- abort_if(!$rl, 400, 'Too many requests');
-
- $this->validate($request, [
- 'email' => [
- 'required',
- 'string',
- 'email',
- 'max:255',
- 'unique:users',
- function ($attribute, $value, $fail) {
- $banned = EmailService::isBanned($value);
- if($banned) {
- return $fail('Email is invalid.');
- }
- },
- ],
- 'username' => [
- 'required',
- 'min:2',
- 'max:15',
- 'unique:users',
- function ($attribute, $value, $fail) {
- $dash = substr_count($value, '-');
- $underscore = substr_count($value, '_');
- $period = substr_count($value, '.');
-
- if(ends_with($value, ['.php', '.js', '.css'])) {
- return $fail('Username is invalid.');
- }
-
- if(($dash + $underscore + $period) > 1) {
- return $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
- }
-
- if (!ctype_alnum($value[0])) {
- return $fail('Username is invalid. Must start with a letter or number.');
- }
-
- if (!ctype_alnum($value[strlen($value) - 1])) {
- return $fail('Username is invalid. Must end with a letter or number.');
- }
-
- $val = str_replace(['_', '.', '-'], '', $value);
- if(!ctype_alnum($val)) {
- return $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
- }
-
- $restricted = RestrictedNames::get();
- if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
- return $fail('Username cannot be used.');
- }
- },
- ],
- 'password' => 'required|string|min:8',
- ]);
-
- $email = $request->input('email');
- $username = $request->input('username');
- $password = $request->input('password');
-
- if(config('database.default') == 'pgsql') {
- $username = strtolower($username);
- $email = strtolower($email);
- }
-
- $user = new User;
- $user->name = $username;
- $user->username = $username;
- $user->email = $email;
- $user->password = Hash::make($password);
- $user->register_source = 'app';
- $user->app_register_ip = $request->ip();
- $user->app_register_token = Str::random(40);
- $user->save();
-
- $rtoken = Str::random(64);
-
- $verify = new EmailVerification();
- $verify->user_id = $user->id;
- $verify->email = $user->email;
- $verify->user_token = $user->app_register_token;
- $verify->random_token = $rtoken;
- $verify->save();
-
- $params = http_build_query([
- 'ut' => $user->app_register_token,
- 'rt' => $rtoken,
- 'ea' => base64_encode($user->email)
- ]);
- $appUrl = url('/api/v1.1/auth/iarer?'. $params);
-
- Mail::to($user->email)->send(new ConfirmAppEmail($verify, $appUrl));
-
- return response()->json([
- 'success' => true,
- ]);
- }
-
- public function inAppRegistrationEmailRedirect(Request $request)
- {
- $this->validate($request, [
- 'ut' => 'required',
- 'rt' => 'required',
- 'ea' => 'required'
- ]);
- $ut = $request->input('ut');
- $rt = $request->input('rt');
- $ea = $request->input('ea');
- $params = http_build_query([
- 'ut' => $ut,
- 'rt' => $rt,
- 'domain' => config('pixelfed.domain.app'),
- 'ea' => $ea
- ]);
- $url = 'pixelfed://confirm-account/'. $ut . '?' . $params;
- return redirect()->away($url);
- }
-
- public function inAppRegistrationConfirm(Request $request)
- {
- abort_if($request->user(), 404);
- abort_unless((bool) config_cache('pixelfed.open_registration'), 404);
- abort_unless((bool) config_cache('pixelfed.allow_app_registration'), 404);
- abort_unless($request->hasHeader('X-PIXELFED-APP'), 403);
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $rl = RateLimiter::attempt('pf:apiv1.1:iarc:'.$request->ip(), config('pixelfed.app_registration_confirm_rate_limit_attempts', 20), function(){}, config('pixelfed.app_registration_confirm_rate_limit_decay', 1800));
- abort_if(!$rl, 429, 'Too many requests');
-
- $this->validate($request, [
- 'user_token' => 'required',
- 'random_token' => 'required',
- 'email' => 'required'
- ]);
-
- $verify = EmailVerification::whereEmail($request->input('email'))
- ->whereUserToken($request->input('user_token'))
- ->whereRandomToken($request->input('random_token'))
- ->first();
-
- if(!$verify) {
- return response()->json(['error' => 'Invalid tokens'], 403);
- }
-
- if($verify->created_at->lt(now()->subHours(24))) {
- $verify->delete();
- return response()->json(['error' => 'Invalid tokens'], 403);
- }
-
- $user = User::findOrFail($verify->user_id);
- $user->email_verified_at = now();
- $user->last_active_at = now();
- $user->save();
-
- $token = $user->createToken('Pixelfed');
-
- return response()->json([
- 'access_token' => $token->accessToken
- ]);
- }
-
- public function archive(Request $request, $id)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('write'), 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $status = Status::whereNull('in_reply_to_id')
- ->whereNull('reblog_of_id')
- ->whereProfileId($request->user()->profile_id)
- ->findOrFail($id);
-
- if($status->scope === 'archived') {
- return [200];
- }
-
- $archive = new StatusArchived;
- $archive->status_id = $status->id;
- $archive->profile_id = $status->profile_id;
- $archive->original_scope = $status->scope;
- $archive->save();
-
- $status->scope = 'archived';
- $status->visibility = 'draft';
- $status->save();
- StatusService::del($status->id, true);
- AccountService::syncPostCount($status->profile_id);
-
- return [200];
- }
-
- public function unarchive(Request $request, $id)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('write'), 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $status = Status::whereNull('in_reply_to_id')
- ->whereNull('reblog_of_id')
- ->whereProfileId($request->user()->profile_id)
- ->findOrFail($id);
-
- if($status->scope !== 'archived') {
- return [200];
- }
-
- $archive = StatusArchived::whereStatusId($status->id)
- ->whereProfileId($status->profile_id)
- ->firstOrFail();
-
- $status->scope = $archive->original_scope;
- $status->visibility = $archive->original_scope;
- $status->save();
- $archive->delete();
- StatusService::del($status->id, true);
- AccountService::syncPostCount($status->profile_id);
-
- return [200];
- }
-
- public function archivedPosts(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $statuses = Status::whereProfileId($request->user()->profile_id)
- ->whereScope('archived')
- ->orderByDesc('id')
- ->cursorPaginate(10);
-
- return StatusStateless::collection($statuses);
- }
-
- public function placesById(Request $request, $id, $slug)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $place = Place::whereSlug($slug)->findOrFail($id);
-
- $posts = Cache::remember('pf-api:v1.1:places-by-id:' . $place->id, 3600, function() use($place) {
- return Status::wherePlaceId($place->id)
- ->whereNull('uri')
- ->whereScope('public')
- ->orderByDesc('created_at')
- ->limit(60)
- ->pluck('id');
- });
-
- $posts = $posts->map(function($id) {
- return StatusService::get($id);
- })
- ->filter()
- ->values();
-
- return [
- 'place' =>
- [
- 'id' => $place->id,
- 'name' => $place->name,
- 'slug' => $place->slug,
- 'country' => $place->country,
- 'lat' => $place->lat,
- 'long' => $place->long
- ],
- 'posts' => $posts];
- }
-
- public function moderatePost(Request $request, $id)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_if($request->user()->is_admin != true, 403);
- abort_unless($request->user()->tokenCan('admin:write'), 403);
-
- if(config('pixelfed.bouncer.cloud_ips.ban_signups')) {
- abort_if(BouncerService::checkIp($request->ip()), 404);
- }
-
- $this->validate($request, [
- 'action' => 'required|in:cw,mark-public,mark-unlisted,mark-private,mark-spammer,delete'
- ]);
-
- $action = $request->input('action');
- $status = Status::find($id);
-
- if(!$status) {
- return response()->json(['error' => 'Cannot find status'], 400);
- }
-
- if($status->uri == null) {
- if($status->profile->user && $status->profile->user->is_admin) {
- return response()->json(['error' => 'Cannot moderate admin accounts'], 400);
- }
- }
-
- if($action == 'mark-spammer') {
- $status->profile->update([
- 'unlisted' => true,
- 'cw' => true,
- 'no_autolink' => true
- ]);
-
- Status::whereProfileId($status->profile_id)
- ->get()
- ->each(function($s) {
- if(in_array($s->scope, ['public', 'unlisted'])) {
- $s->scope = 'private';
- $s->visibility = 'private';
- }
- $s->is_nsfw = true;
- $s->save();
- StatusService::del($s->id, true);
- });
-
- Cache::forget('pf:bouncer_v0:exemption_by_pid:' . $status->profile_id);
- Cache::forget('pf:bouncer_v0:recent_by_pid:' . $status->profile_id);
- Cache::forget('admin-dash:reports:spam-count');
- } else if ($action == 'cw') {
- $state = $status->is_nsfw;
- $status->is_nsfw = !$state;
- $status->save();
- StatusService::del($status->id);
- } else if ($action == 'mark-public') {
- $state = $status->scope;
- $status->scope = 'public';
- $status->visibility = 'public';
- $status->save();
- StatusService::del($status->id, true);
- if($state !== 'public') {
- if($status->uri) {
- if($status->in_reply_to_id == null && $status->reblog_of_id == null) {
- NetworkTimelineService::add($status->id);
- }
- } else {
- if($status->in_reply_to_id == null && $status->reblog_of_id == null) {
- PublicTimelineService::add($status->id);
- }
- }
- }
- } else if ($action == 'mark-unlisted') {
- $state = $status->scope;
- $status->scope = 'unlisted';
- $status->visibility = 'unlisted';
- $status->save();
- StatusService::del($status->id);
- if($state == 'public') {
- PublicTimelineService::del($status->id);
- NetworkTimelineService::del($status->id);
- }
- } else if ($action == 'mark-private') {
- $state = $status->scope;
- $status->scope = 'private';
- $status->visibility = 'private';
- $status->save();
- StatusService::del($status->id);
- if($state == 'public') {
- PublicTimelineService::del($status->id);
- NetworkTimelineService::del($status->id);
- }
- } else if ($action == 'delete') {
- PublicTimelineService::del($status->id);
- NetworkTimelineService::del($status->id);
- Cache::forget('_api:statuses:recent_9:' . $status->profile_id);
- Cache::forget('profile:status_count:' . $status->profile_id);
- Cache::forget('profile:embed:' . $status->profile_id);
- StatusService::del($status->id, true);
- Cache::forget('profile:status_count:'.$status->profile_id);
- $status->uri ? RemoteStatusDelete::dispatch($status) : StatusDelete::dispatch($status);
- return [];
- }
-
- Cache::forget('_api:statuses:recent_9:'.$status->profile_id);
-
- return StatusService::get($status->id, false);
- }
-
- public function getWebSettings(Request $request)
- {
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('read'), 403);
+ protected $fractal;
+
+ public function __construct()
+ {
+ $this->fractal = new Fractal\Manager();
+ $this->fractal->setSerializer(new ArraySerializer());
+ }
+
+ public function json($res, $code = 200, $headers = [])
+ {
+ return response()->json($res, $code, $headers, JSON_UNESCAPED_SLASHES);
+ }
+
+ public function error($msg, $code = 400, $extra = [], $headers = [])
+ {
+ $res = [
+ 'msg' => $msg,
+ 'code' => $code,
+ ];
+
+ return response()->json(array_merge($res, $extra), $code, $headers, JSON_UNESCAPED_SLASHES);
+ }
+
+ public function report(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('write'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $report_type = $request->input('report_type');
+ $object_id = $request->input('object_id');
+ $object_type = $request->input('object_type');
+
+ $types = [
+ 'spam',
+ 'sensitive',
+ 'abusive',
+ 'underage',
+ 'violence',
+ 'copyright',
+ 'impersonation',
+ 'scam',
+ 'terrorism',
+ ];
+
+ if (! $report_type || ! $object_id || ! $object_type) {
+ return $this->error('Invalid or missing parameters', 400, ['error_code' => 'ERROR_INVALID_PARAMS']);
+ }
+
+ if (! in_array($report_type, $types)) {
+ return $this->error('Invalid report type', 400, ['error_code' => 'ERROR_TYPE_INVALID']);
+ }
+
+ if ($object_type === 'user' && $object_id == $user->profile_id) {
+ return $this->error('Cannot self report', 400, ['error_code' => 'ERROR_NO_SELF_REPORTS']);
+ }
+
+ $rpid = null;
+
+ switch ($object_type) {
+ case 'post':
+ $object = Status::find($object_id);
+ if (! $object) {
+ return $this->error('Invalid object id', 400, ['error_code' => 'ERROR_INVALID_OBJECT_ID']);
+ }
+ $object_type = 'App\Status';
+ $exists = Report::whereUserId($user->id)
+ ->whereObjectId($object->id)
+ ->whereObjectType('App\Status')
+ ->count();
+
+ $rpid = $object->profile_id;
+ break;
+
+ case 'user':
+ $object = Profile::find($object_id);
+ if (! $object) {
+ return $this->error('Invalid object id', 400, ['error_code' => 'ERROR_INVALID_OBJECT_ID']);
+ }
+ $object_type = 'App\Profile';
+ $exists = Report::whereUserId($user->id)
+ ->whereObjectId($object->id)
+ ->whereObjectType('App\Profile')
+ ->count();
+ $rpid = $object->id;
+ break;
+
+ default:
+ return $this->error('Invalid report type', 400, ['error_code' => 'ERROR_REPORT_OBJECT_TYPE_INVALID']);
+ break;
+ }
+
+ if ($exists !== 0) {
+ return $this->error('Duplicate report', 400, ['error_code' => 'ERROR_REPORT_DUPLICATE']);
+ }
+
+ if ($object->profile_id == $user->profile_id) {
+ return $this->error('Cannot self report', 400, ['error_code' => 'ERROR_NO_SELF_REPORTS']);
+ }
+
+ $report = new Report;
+ $report->profile_id = $user->profile_id;
+ $report->user_id = $user->id;
+ $report->object_id = $object->id;
+ $report->object_type = $object_type;
+ $report->reported_profile_id = $rpid;
+ $report->type = $report_type;
+ $report->save();
+
+ if (config('instance.reports.email.enabled')) {
+ ReportNotifyAdminViaEmail::dispatch($report)->onQueue('default');
+ }
+
+ $res = [
+ 'msg' => 'Successfully sent report',
+ 'code' => 200,
+ ];
+
+ return $this->json($res);
+ }
+
+ /**
+ * DELETE /api/v1.1/accounts/avatar
+ *
+ * @return \App\Transformer\Api\AccountTransformer
+ */
+ public function deleteAvatar(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('write'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $avatar = $user->profile->avatar;
+
+ if ($avatar->media_path == 'public/avatars/default.png' ||
+ $avatar->media_path == 'public/avatars/default.jpg'
+ ) {
+ return AccountService::get($user->profile_id);
+ }
+
+ if (is_file(storage_path('app/'.$avatar->media_path))) {
+ @unlink(storage_path('app/'.$avatar->media_path));
+ }
+
+ $avatar->media_path = 'public/avatars/default.jpg';
+ $avatar->change_count = $avatar->change_count + 1;
+ $avatar->save();
+
+ Cache::forget('avatar:'.$user->profile_id);
+ Cache::forget("avatar:{$user->profile_id}");
+ Cache::forget('user:account:id:'.$user->id);
+ AccountService::del($user->profile_id);
+
+ return AccountService::get($user->profile_id);
+ }
+
+ /**
+ * GET /api/v1.1/accounts/{id}/posts
+ *
+ * @return \App\Transformer\Api\StatusTransformer
+ */
+ public function accountPosts(Request $request, $id)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $account = AccountService::get($id);
+
+ if (! $account || $account['username'] !== $request->input('username')) {
+ return $this->json([]);
+ }
+
+ $posts = ProfileStatusService::get($id);
+
+ if (! $posts) {
+ return $this->json([]);
+ }
+
+ $res = collect($posts)
+ ->map(function ($id) {
+ return StatusService::get($id);
+ })
+ ->filter(function ($post) {
+ return $post && isset($post['account']);
+ })
+ ->toArray();
+
+ return $this->json($res);
+ }
+
+ /**
+ * POST /api/v1.1/accounts/change-password
+ *
+ * @return \App\Transformer\Api\AccountTransformer
+ */
+ public function accountChangePassword(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('write'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $this->validate($request, [
+ 'current_password' => 'bail|required|current_password',
+ 'new_password' => 'required|min:'.config('pixelfed.min_password_length', 8),
+ 'confirm_password' => 'required|same:new_password',
+ ], [
+ 'current_password' => 'The password you entered is incorrect',
+ ]);
+
+ $user->password = bcrypt($request->input('new_password'));
+ $user->save();
+
+ $log = new AccountLog;
+ $log->user_id = $user->id;
+ $log->item_id = $user->id;
+ $log->item_type = 'App\User';
+ $log->action = 'account.edit.password';
+ $log->message = 'Password changed';
+ $log->link = null;
+ $log->ip_address = $request->ip();
+ $log->user_agent = $request->userAgent();
+ $log->save();
+
+ Mail::to($request->user())->send(new PasswordChange($user));
+
+ return $this->json(AccountService::get($user->profile_id));
+ }
+
+ /**
+ * GET /api/v1.1/accounts/login-activity
+ *
+ * @return array
+ */
+ public function accountLoginActivity(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+ $agent = new Agent();
+ $currentIp = $request->ip();
+
+ $activity = AccountLog::whereUserId($user->id)
+ ->whereAction('auth.login')
+ ->orderBy('created_at', 'desc')
+ ->groupBy('ip_address')
+ ->limit(10)
+ ->get()
+ ->map(function ($item) use ($agent, $currentIp) {
+ $agent->setUserAgent($item->user_agent);
+
+ return [
+ 'id' => $item->id,
+ 'action' => $item->action,
+ 'ip' => $item->ip_address,
+ 'ip_current' => $item->ip_address === $currentIp,
+ 'is_mobile' => $agent->isMobile(),
+ 'device' => $agent->device(),
+ 'browser' => $agent->browser(),
+ 'platform' => $agent->platform(),
+ 'created_at' => $item->created_at->format('c'),
+ ];
+ });
+
+ return $this->json($activity);
+ }
+
+ /**
+ * GET /api/v1.1/accounts/two-factor
+ *
+ * @return array
+ */
+ public function accountTwoFactor(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $res = [
+ 'active' => (bool) $user->{'2fa_enabled'},
+ 'setup_at' => $user->{'2fa_setup_at'},
+ ];
+
+ return $this->json($res);
+ }
+
+ /**
+ * GET /api/v1.1/accounts/emails-from-pixelfed
+ *
+ * @return array
+ */
+ public function accountEmailsFromPixelfed(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+ $from = config('mail.from.address');
+
+ $emailVerifications = EmailVerification::whereUserId($user->id)
+ ->orderByDesc('id')
+ ->where('created_at', '>', now()->subDays(14))
+ ->limit(10)
+ ->get()
+ ->map(function ($mail) use ($user, $from) {
+ return [
+ 'type' => 'Email Verification',
+ 'subject' => 'Confirm Email',
+ 'to_address' => $user->email,
+ 'from_address' => $from,
+ 'created_at' => str_replace('@', 'at', $mail->created_at->format('M j, Y @ g:i:s A')),
+ ];
+ })
+ ->toArray();
+
+ $passwordResets = DB::table('password_resets')
+ ->whereEmail($user->email)
+ ->where('created_at', '>', now()->subDays(14))
+ ->orderByDesc('created_at')
+ ->limit(10)
+ ->get()
+ ->map(function ($mail) use ($user, $from) {
+ return [
+ 'type' => 'Password Reset',
+ 'subject' => 'Reset Password Notification',
+ 'to_address' => $user->email,
+ 'from_address' => $from,
+ 'created_at' => str_replace('@', 'at', now()->parse($mail->created_at)->format('M j, Y @ g:i:s A')),
+ ];
+ })
+ ->toArray();
+
+ $passwordChanges = AccountLog::whereUserId($user->id)
+ ->whereAction('account.edit.password')
+ ->where('created_at', '>', now()->subDays(14))
+ ->orderByDesc('created_at')
+ ->limit(10)
+ ->get()
+ ->map(function ($mail) use ($user, $from) {
+ return [
+ 'type' => 'Password Change',
+ 'subject' => 'Password Change',
+ 'to_address' => $user->email,
+ 'from_address' => $from,
+ 'created_at' => str_replace('@', 'at', now()->parse($mail->created_at)->format('M j, Y @ g:i:s A')),
+ ];
+ })
+ ->toArray();
+
+ $res = collect([])
+ ->merge($emailVerifications)
+ ->merge($passwordResets)
+ ->merge($passwordChanges)
+ ->sortByDesc('created_at')
+ ->values();
+
+ return $this->json($res);
+ }
+
+ /**
+ * GET /api/v1.1/accounts/apps-and-applications
+ *
+ * @return array
+ */
+ public function accountApps(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ $user = $request->user();
+ abort_if($user->status != null, 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $res = $user->tokens->sortByDesc('created_at')->take(10)->map(function ($token, $key) use ($request) {
+ return [
+ 'id' => $token->id,
+ 'current_session' => $request->user()->token()->id == $token->id,
+ 'name' => $token->client->name,
+ 'scopes' => $token->scopes,
+ 'revoked' => $token->revoked,
+ 'created_at' => str_replace('@', 'at', now()->parse($token->created_at)->format('M j, Y @ g:i:s A')),
+ 'expires_at' => str_replace('@', 'at', now()->parse($token->expires_at)->format('M j, Y @ g:i:s A')),
+ ];
+ });
+
+ return $this->json($res);
+ }
+
+ public function inAppRegistrationPreFlightCheck(Request $request)
+ {
+ return [
+ 'open' => (bool) config_cache('pixelfed.open_registration'),
+ 'iara' => (bool) config_cache('pixelfed.allow_app_registration'),
+ ];
+ }
+
+ public function inAppRegistration(Request $request)
+ {
+ abort_if($request->user(), 404);
+ abort_unless((bool) config_cache('pixelfed.open_registration'), 404);
+ abort_unless((bool) config_cache('pixelfed.allow_app_registration'), 404);
+ abort_unless($request->hasHeader('X-PIXELFED-APP'), 403);
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $rl = RateLimiter::attempt('pf:apiv1.1:iar:'.$request->ip(), config('pixelfed.app_registration_rate_limit_attempts', 3), function () {
+ }, config('pixelfed.app_registration_rate_limit_decay', 1800));
+ abort_if(! $rl, 400, 'Too many requests');
+
+ $this->validate($request, [
+ 'email' => [
+ 'required',
+ 'string',
+ 'email',
+ 'max:255',
+ 'unique:users',
+ function ($attribute, $value, $fail) {
+ $banned = EmailService::isBanned($value);
+ if ($banned) {
+ return $fail('Email is invalid.');
+ }
+ },
+ ],
+ 'username' => [
+ 'required',
+ 'min:2',
+ 'max:15',
+ 'unique:users',
+ function ($attribute, $value, $fail) {
+ $dash = substr_count($value, '-');
+ $underscore = substr_count($value, '_');
+ $period = substr_count($value, '.');
+
+ if (ends_with($value, ['.php', '.js', '.css'])) {
+ return $fail('Username is invalid.');
+ }
+
+ if (($dash + $underscore + $period) > 1) {
+ return $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
+ }
+
+ if (! ctype_alnum($value[0])) {
+ return $fail('Username is invalid. Must start with a letter or number.');
+ }
+
+ if (! ctype_alnum($value[strlen($value) - 1])) {
+ return $fail('Username is invalid. Must end with a letter or number.');
+ }
+
+ $val = str_replace(['_', '.', '-'], '', $value);
+ if (! ctype_alnum($val)) {
+ return $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
+ }
+
+ $restricted = RestrictedNames::get();
+ if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
+ return $fail('Username cannot be used.');
+ }
+ },
+ ],
+ 'password' => 'required|string|min:8',
+ ]);
+
+ $email = $request->input('email');
+ $username = $request->input('username');
+ $password = $request->input('password');
+
+ if (config('database.default') == 'pgsql') {
+ $username = strtolower($username);
+ $email = strtolower($email);
+ }
+
+ $user = new User;
+ $user->name = $username;
+ $user->username = $username;
+ $user->email = $email;
+ $user->password = Hash::make($password);
+ $user->register_source = 'app';
+ $user->app_register_ip = $request->ip();
+ $user->app_register_token = Str::random(40);
+ $user->save();
+
+ $rtoken = Str::random(64);
+
+ $verify = new EmailVerification();
+ $verify->user_id = $user->id;
+ $verify->email = $user->email;
+ $verify->user_token = $user->app_register_token;
+ $verify->random_token = $rtoken;
+ $verify->save();
+
+ $params = http_build_query([
+ 'ut' => $user->app_register_token,
+ 'rt' => $rtoken,
+ 'ea' => base64_encode($user->email),
+ ]);
+ $appUrl = url('/api/v1.1/auth/iarer?'.$params);
+
+ Mail::to($user->email)->send(new ConfirmAppEmail($verify, $appUrl));
+
+ return response()->json([
+ 'success' => true,
+ ]);
+ }
+
+ public function inAppRegistrationEmailRedirect(Request $request)
+ {
+ $this->validate($request, [
+ 'ut' => 'required',
+ 'rt' => 'required',
+ 'ea' => 'required',
+ ]);
+ $ut = $request->input('ut');
+ $rt = $request->input('rt');
+ $ea = $request->input('ea');
+ $params = http_build_query([
+ 'ut' => $ut,
+ 'rt' => $rt,
+ 'domain' => config('pixelfed.domain.app'),
+ 'ea' => $ea,
+ ]);
+ $url = 'pixelfed://confirm-account/'.$ut.'?'.$params;
+
+ return redirect()->away($url);
+ }
+
+ public function inAppRegistrationConfirm(Request $request)
+ {
+ abort_if($request->user(), 404);
+ abort_unless((bool) config_cache('pixelfed.open_registration'), 404);
+ abort_unless((bool) config_cache('pixelfed.allow_app_registration'), 404);
+ abort_unless($request->hasHeader('X-PIXELFED-APP'), 403);
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $rl = RateLimiter::attempt('pf:apiv1.1:iarc:'.$request->ip(), config('pixelfed.app_registration_confirm_rate_limit_attempts', 20), function () {
+ }, config('pixelfed.app_registration_confirm_rate_limit_decay', 1800));
+ abort_if(! $rl, 429, 'Too many requests');
+
+ $request->validate([
+ 'user_token' => 'required',
+ 'random_token' => 'required',
+ 'email' => 'required',
+ ]);
+
+ $verify = EmailVerification::whereEmail($request->input('email'))
+ ->whereUserToken($request->input('user_token'))
+ ->whereRandomToken($request->input('random_token'))
+ ->first();
+
+ if (! $verify) {
+ return response()->json(['error' => 'Invalid tokens'], 403);
+ }
+
+ if ($verify->created_at->lt(now()->subHours(24))) {
+ $verify->delete();
+
+ return response()->json(['error' => 'Invalid tokens'], 403);
+ }
+
+ $user = User::findOrFail($verify->user_id);
+ $user->email_verified_at = now();
+ $user->last_active_at = now();
+ $user->save();
+
+ $token = $user->createToken('Pixelfed', ['read', 'write', 'follow', 'admin:read', 'admin:write', 'push']);
+
+ return response()->json([
+ 'access_token' => $token->accessToken,
+ ]);
+ }
+
+ public function archive(Request $request, $id)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('write'), 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $status = Status::whereNull('in_reply_to_id')
+ ->whereNull('reblog_of_id')
+ ->whereProfileId($request->user()->profile_id)
+ ->findOrFail($id);
+
+ if ($status->scope === 'archived') {
+ return [200];
+ }
+
+ $archive = new StatusArchived;
+ $archive->status_id = $status->id;
+ $archive->profile_id = $status->profile_id;
+ $archive->original_scope = $status->scope;
+ $archive->save();
+
+ $status->scope = 'archived';
+ $status->visibility = 'draft';
+ $status->save();
+ StatusService::del($status->id, true);
+ AccountService::syncPostCount($status->profile_id);
+
+ return [200];
+ }
+
+ public function unarchive(Request $request, $id)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('write'), 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $status = Status::whereNull('in_reply_to_id')
+ ->whereNull('reblog_of_id')
+ ->whereProfileId($request->user()->profile_id)
+ ->findOrFail($id);
+
+ if ($status->scope !== 'archived') {
+ return [200];
+ }
+
+ $archive = StatusArchived::whereStatusId($status->id)
+ ->whereProfileId($status->profile_id)
+ ->firstOrFail();
+
+ $status->scope = $archive->original_scope;
+ $status->visibility = $archive->original_scope;
+ $status->save();
+ $archive->delete();
+ StatusService::del($status->id, true);
+ AccountService::syncPostCount($status->profile_id);
+
+ return [200];
+ }
+
+ public function archivedPosts(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $statuses = Status::whereProfileId($request->user()->profile_id)
+ ->whereScope('archived')
+ ->orderByDesc('id')
+ ->cursorPaginate(10);
+
+ return StatusStateless::collection($statuses);
+ }
+
+ public function placesById(Request $request, $id, $slug)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $place = Place::whereSlug($slug)->findOrFail($id);
+
+ $posts = Cache::remember('pf-api:v1.1:places-by-id:'.$place->id, 3600, function () use ($place) {
+ return Status::wherePlaceId($place->id)
+ ->whereNull('uri')
+ ->whereScope('public')
+ ->orderByDesc('created_at')
+ ->limit(60)
+ ->pluck('id');
+ });
+
+ $posts = $posts->map(function ($id) {
+ return StatusService::get($id);
+ })
+ ->filter()
+ ->values();
+
+ return [
+ 'place' => [
+ 'id' => $place->id,
+ 'name' => $place->name,
+ 'slug' => $place->slug,
+ 'country' => $place->country,
+ 'lat' => $place->lat,
+ 'long' => $place->long,
+ ],
+ 'posts' => $posts];
+ }
+
+ public function moderatePost(Request $request, $id)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_if($request->user()->is_admin != true, 403);
+ abort_unless($request->user()->tokenCan('admin:write'), 403);
+
+ if (config('pixelfed.bouncer.cloud_ips.ban_signups')) {
+ abort_if(BouncerService::checkIp($request->ip()), 404);
+ }
+
+ $this->validate($request, [
+ 'action' => 'required|in:cw,mark-public,mark-unlisted,mark-private,mark-spammer,delete',
+ ]);
+
+ $action = $request->input('action');
+ $status = Status::find($id);
+
+ if (! $status) {
+ return response()->json(['error' => 'Cannot find status'], 400);
+ }
+
+ if ($status->uri == null) {
+ if ($status->profile->user && $status->profile->user->is_admin) {
+ return response()->json(['error' => 'Cannot moderate admin accounts'], 400);
+ }
+ }
+
+ if ($action == 'mark-spammer') {
+ $status->profile->update([
+ 'unlisted' => true,
+ 'cw' => true,
+ 'no_autolink' => true,
+ ]);
+
+ Status::whereProfileId($status->profile_id)
+ ->get()
+ ->each(function ($s) {
+ if (in_array($s->scope, ['public', 'unlisted'])) {
+ $s->scope = 'private';
+ $s->visibility = 'private';
+ }
+ $s->is_nsfw = true;
+ $s->save();
+ StatusService::del($s->id, true);
+ });
+
+ Cache::forget('pf:bouncer_v0:exemption_by_pid:'.$status->profile_id);
+ Cache::forget('pf:bouncer_v0:recent_by_pid:'.$status->profile_id);
+ Cache::forget('admin-dash:reports:spam-count');
+ } elseif ($action == 'cw') {
+ $state = $status->is_nsfw;
+ $status->is_nsfw = ! $state;
+ $status->save();
+ StatusService::del($status->id);
+ } elseif ($action == 'mark-public') {
+ $state = $status->scope;
+ $status->scope = 'public';
+ $status->visibility = 'public';
+ $status->save();
+ StatusService::del($status->id, true);
+ if ($state !== 'public') {
+ if ($status->uri) {
+ if ($status->in_reply_to_id == null && $status->reblog_of_id == null) {
+ NetworkTimelineService::add($status->id);
+ }
+ } else {
+ if ($status->in_reply_to_id == null && $status->reblog_of_id == null) {
+ PublicTimelineService::add($status->id);
+ }
+ }
+ }
+ } elseif ($action == 'mark-unlisted') {
+ $state = $status->scope;
+ $status->scope = 'unlisted';
+ $status->visibility = 'unlisted';
+ $status->save();
+ StatusService::del($status->id);
+ if ($state == 'public') {
+ PublicTimelineService::del($status->id);
+ NetworkTimelineService::del($status->id);
+ }
+ } elseif ($action == 'mark-private') {
+ $state = $status->scope;
+ $status->scope = 'private';
+ $status->visibility = 'private';
+ $status->save();
+ StatusService::del($status->id);
+ if ($state == 'public') {
+ PublicTimelineService::del($status->id);
+ NetworkTimelineService::del($status->id);
+ }
+ } elseif ($action == 'delete') {
+ PublicTimelineService::del($status->id);
+ NetworkTimelineService::del($status->id);
+ Cache::forget('_api:statuses:recent_9:'.$status->profile_id);
+ Cache::forget('profile:status_count:'.$status->profile_id);
+ Cache::forget('profile:embed:'.$status->profile_id);
+ StatusService::del($status->id, true);
+ Cache::forget('profile:status_count:'.$status->profile_id);
+ $status->uri ? RemoteStatusDelete::dispatch($status) : StatusDelete::dispatch($status);
+
+ return [];
+ }
+
+ Cache::forget('_api:statuses:recent_9:'.$status->profile_id);
+
+ return StatusService::get($status->id, false);
+ }
+
+ public function getWebSettings(Request $request)
+ {
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('read'), 403);
$uid = $request->user()->id;
$settings = UserSetting::firstOrCreate([
- 'user_id' => $uid
+ 'user_id' => $uid,
]);
- if(!$settings->other) {
+ if (! $settings->other) {
return [];
}
- return $settings->other;
- }
+
+ return $settings->other;
+ }
public function setWebSettings(Request $request)
{
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('write'), 403);
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('write'), 403);
$this->validate($request, [
'field' => 'required|in:enable_reblogs,hide_reblog_banner',
- 'value' => 'required'
+ 'value' => 'required',
]);
$field = $request->input('field');
$value = $request->input('value');
$settings = UserSetting::firstOrCreate([
- 'user_id' => $request->user()->id
+ 'user_id' => $request->user()->id,
]);
- if(!$settings->other) {
+ if (! $settings->other) {
$other = [];
} else {
$other = $settings->other;
@@ -923,18 +928,21 @@ class ApiV1Dot1Controller extends Controller
public function getMutualAccounts(Request $request, $id)
{
- abort_if(!$request->user() || !$request->user()->token(), 403);
- abort_unless($request->user()->tokenCan('follows'), 403);
+ abort_if(! $request->user() || ! $request->user()->token(), 403);
+ abort_unless($request->user()->tokenCan('follows'), 403);
$account = AccountService::get($id, true);
- if(!$account || !isset($account['id'])) { return []; }
+ if (! $account || ! isset($account['id'])) {
+ return [];
+ }
$res = collect(FollowerService::mutualAccounts($request->user()->profile_id, $id))
- ->map(function($accountId) {
+ ->map(function ($accountId) {
return AccountService::get($accountId, true);
})
->filter()
->take(24)
->values();
+
return $this->json($res);
}
}
diff --git a/app/Http/Controllers/DirectMessageController.php b/app/Http/Controllers/DirectMessageController.php
index 0d91d4f17..af51d5080 100644
--- a/app/Http/Controllers/DirectMessageController.php
+++ b/app/Http/Controllers/DirectMessageController.php
@@ -309,6 +309,7 @@ class DirectMessageController extends Controller
$user = $request->user();
abort_if($user->has_roles && !UserRoleService::can('can-direct-message', $user->id), 403, 'Invalid permissions for this action');
+ abort_if($user->created_at->gt(now()->subHours(72)), 400, 'You need to wait a bit before you can DM another account');
$profile = $user->profile;
$recipient = Profile::where('id', '!=', $profile->id)->findOrFail($request->input('to_id'));
diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php
index 65a756eaf..3fc877452 100644
--- a/app/Http/Controllers/ProfileController.php
+++ b/app/Http/Controllers/ProfileController.php
@@ -172,7 +172,7 @@ class ProfileController extends Controller
$user = $this->getCachedUser($username);
- abort_if(!$user, 404);
+ abort_if(! $user, 404);
return redirect($user->url());
}
@@ -254,7 +254,7 @@ class ProfileController extends Controller
abort_if(! $profile || $profile['locked'] || ! $profile['local'], 404);
- $aiCheck = Cache::remember('profile:ai-check:spam-login:'.$profile['id'], 86400, function () use ($profile) {
+ $aiCheck = Cache::remember('profile:ai-check:spam-login:'.$profile['id'], 3600, function () use ($profile) {
$uid = User::whereProfileId($profile['id'])->first();
if (! $uid) {
return true;
@@ -348,7 +348,7 @@ class ProfileController extends Controller
return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
}
- $aiCheck = Cache::remember('profile:ai-check:spam-login:'.$profile->id, 86400, function () use ($profile) {
+ $aiCheck = Cache::remember('profile:ai-check:spam-login:'.$profile->id, 3600, function () use ($profile) {
$exists = AccountInterstitial::whereUserId($profile->user_id)->where('is_spam', 1)->count();
if ($exists) {
return true;
@@ -373,7 +373,7 @@ class ProfileController extends Controller
public function stories(Request $request, $username)
{
- abort_if(!(bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
+ abort_if(! (bool) config_cache('instance.stories.enabled') || ! $request->user(), 404);
$profile = Profile::whereNull('domain')->whereUsername($username)->firstOrFail();
$pid = $profile->id;
$authed = Auth::user()->profile_id;
diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php
index 7f77f9a81..e0864a4a7 100644
--- a/app/Http/Controllers/StatusController.php
+++ b/app/Http/Controllers/StatusController.php
@@ -8,6 +8,7 @@ use App\Jobs\SharePipeline\UndoSharePipeline;
use App\Jobs\StatusPipeline\RemoteStatusDelete;
use App\Jobs\StatusPipeline\StatusDelete;
use App\Profile;
+use App\Services\AccountService;
use App\Services\HashidService;
use App\Services\ReblogService;
use App\Services\StatusService;
@@ -113,19 +114,33 @@ class StatusController extends Controller
return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
}
- $profile = Profile::whereNull(['domain', 'status'])
- ->whereIsPrivate(false)
- ->whereUsername($username)
- ->first();
+ $status = StatusService::get($id);
- if (! $profile) {
+ if (
+ ! $status ||
+ ! isset($status['account'], $status['account']['id'], $status['local']) ||
+ ! $status['local'] ||
+ strtolower($status['account']['username']) !== strtolower($username)
+ ) {
+ $content = view('status.embed-removed');
+
+ return response($content, 404)->header('X-Frame-Options', 'ALLOWALL');
+ }
+
+ $profile = AccountService::get($status['account']['id'], true);
+
+ if (! $profile || $profile['locked'] || ! $profile['local']) {
$content = view('status.embed-removed');
return response($content)->header('X-Frame-Options', 'ALLOWALL');
}
- $aiCheck = Cache::remember('profile:ai-check:spam-login:'.$profile->id, 86400, function () use ($profile) {
- $exists = AccountInterstitial::whereUserId($profile->user_id)->where('is_spam', 1)->count();
+ $aiCheck = Cache::remember('profile:ai-check:spam-login:'.$profile['id'], 3600, function () use ($profile) {
+ $user = Profile::find($profile['id']);
+ if (! $user) {
+ return true;
+ }
+ $exists = AccountInterstitial::whereUserId($user->user_id)->where('is_spam', 1)->count();
if ($exists) {
return true;
}
@@ -138,17 +153,22 @@ class StatusController extends Controller
return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
}
- $status = Status::whereProfileId($profile->id)
- ->whereNull('uri')
- ->whereScope('public')
- ->whereIsNsfw(false)
- ->whereIn('type', ['photo', 'video', 'photo:album'])
- ->find($id);
- if (! $status) {
+
+ $status = StatusService::get($id);
+
+ if (
+ ! $status ||
+ ! isset($status['account'], $status['account']['id']) ||
+ intval($status['account']['id']) !== intval($profile['id']) ||
+ $status['sensitive'] ||
+ $status['visibility'] !== 'public' ||
+ $status['pf_type'] !== 'photo'
+ ) {
$content = view('status.embed-removed');
return response($content)->header('X-Frame-Options', 'ALLOWALL');
}
+
$showLikes = $request->filled('likes') && $request->likes == true;
$showCaption = $request->filled('caption') && $request->caption !== false;
$layout = $request->filled('layout') && $request->layout == 'compact' ? 'compact' : 'full';
diff --git a/app/Like.php b/app/Like.php
index c5b000c66..0c2c7f363 100644
--- a/app/Like.php
+++ b/app/Like.php
@@ -9,7 +9,7 @@ class Like extends Model
{
use SoftDeletes;
- const MAX_PER_DAY = 500;
+ const MAX_PER_DAY = 1500;
/**
* The attributes that should be mutated to dates.
diff --git a/app/Services/ConfigCacheService.php b/app/Services/ConfigCacheService.php
index 626982781..b18c02e36 100644
--- a/app/Services/ConfigCacheService.php
+++ b/app/Services/ConfigCacheService.php
@@ -4,6 +4,7 @@ namespace App\Services;
use App\Models\ConfigCache as ConfigCacheModel;
use Cache;
+use Illuminate\Database\QueryException;
class ConfigCacheService
{
@@ -25,156 +26,159 @@ class ConfigCacheService
return config($key);
}
- return Cache::remember($cacheKey, $ttl, function () use ($key) {
+ try {
+ return Cache::remember($cacheKey, $ttl, function () use ($key) {
+ $allowed = [
+ 'app.name',
+ 'app.short_description',
+ 'app.description',
+ 'app.rules',
- $allowed = [
- 'app.name',
- 'app.short_description',
- 'app.description',
- 'app.rules',
+ 'pixelfed.max_photo_size',
+ 'pixelfed.max_album_length',
+ 'pixelfed.image_quality',
+ 'pixelfed.media_types',
- 'pixelfed.max_photo_size',
- 'pixelfed.max_album_length',
- 'pixelfed.image_quality',
- 'pixelfed.media_types',
+ 'pixelfed.open_registration',
+ 'federation.activitypub.enabled',
+ 'instance.stories.enabled',
+ 'pixelfed.oauth_enabled',
+ 'pixelfed.import.instagram.enabled',
+ 'pixelfed.bouncer.enabled',
- 'pixelfed.open_registration',
- 'federation.activitypub.enabled',
- 'instance.stories.enabled',
- 'pixelfed.oauth_enabled',
- 'pixelfed.import.instagram.enabled',
- 'pixelfed.bouncer.enabled',
+ 'pixelfed.enforce_email_verification',
+ 'pixelfed.max_account_size',
+ 'pixelfed.enforce_account_limit',
- 'pixelfed.enforce_email_verification',
- 'pixelfed.max_account_size',
- 'pixelfed.enforce_account_limit',
+ 'uikit.custom.css',
+ 'uikit.custom.js',
+ 'uikit.show_custom.css',
+ 'uikit.show_custom.js',
+ 'about.title',
- 'uikit.custom.css',
- 'uikit.custom.js',
- 'uikit.show_custom.css',
- 'uikit.show_custom.js',
- 'about.title',
+ 'pixelfed.cloud_storage',
- 'pixelfed.cloud_storage',
+ 'account.autofollow',
+ 'account.autofollow_usernames',
+ 'config.discover.features',
- 'account.autofollow',
- 'account.autofollow_usernames',
- 'config.discover.features',
+ 'instance.has_legal_notice',
+ 'instance.avatar.local_to_cloud',
- 'instance.has_legal_notice',
- 'instance.avatar.local_to_cloud',
+ 'pixelfed.directory',
+ 'app.banner_image',
+ 'pixelfed.directory.submission-key',
+ 'pixelfed.directory.submission-ts',
+ 'pixelfed.directory.has_submitted',
+ 'pixelfed.directory.latest_response',
+ 'pixelfed.directory.is_synced',
+ 'pixelfed.directory.testimonials',
- 'pixelfed.directory',
- 'app.banner_image',
- 'pixelfed.directory.submission-key',
- 'pixelfed.directory.submission-ts',
- 'pixelfed.directory.has_submitted',
- 'pixelfed.directory.latest_response',
- 'pixelfed.directory.is_synced',
- 'pixelfed.directory.testimonials',
+ 'instance.landing.show_directory',
+ 'instance.landing.show_explore',
+ 'instance.admin.pid',
+ 'instance.banner.blurhash',
- 'instance.landing.show_directory',
- 'instance.landing.show_explore',
- 'instance.admin.pid',
- 'instance.banner.blurhash',
+ 'autospam.nlp.enabled',
- 'autospam.nlp.enabled',
+ 'instance.curated_registration.enabled',
- 'instance.curated_registration.enabled',
+ 'federation.migration',
- 'federation.migration',
+ 'pixelfed.max_caption_length',
+ 'pixelfed.max_bio_length',
+ 'pixelfed.max_name_length',
+ 'pixelfed.min_password_length',
+ 'pixelfed.max_avatar_size',
+ 'pixelfed.max_altext_length',
+ 'pixelfed.allow_app_registration',
+ 'pixelfed.app_registration_rate_limit_attempts',
+ 'pixelfed.app_registration_rate_limit_decay',
+ 'pixelfed.app_registration_confirm_rate_limit_attempts',
+ 'pixelfed.app_registration_confirm_rate_limit_decay',
+ 'instance.embed.profile',
+ 'instance.embed.post',
- 'pixelfed.max_caption_length',
- 'pixelfed.max_bio_length',
- 'pixelfed.max_name_length',
- 'pixelfed.min_password_length',
- 'pixelfed.max_avatar_size',
- 'pixelfed.max_altext_length',
- 'pixelfed.allow_app_registration',
- 'pixelfed.app_registration_rate_limit_attempts',
- 'pixelfed.app_registration_rate_limit_decay',
- 'pixelfed.app_registration_confirm_rate_limit_attempts',
- 'pixelfed.app_registration_confirm_rate_limit_decay',
- 'instance.embed.profile',
- 'instance.embed.post',
+ 'captcha.enabled',
+ 'captcha.secret',
+ 'captcha.sitekey',
+ 'captcha.active.login',
+ 'captcha.active.register',
+ 'captcha.triggers.login.enabled',
+ 'captcha.triggers.login.attempts',
+ 'federation.custom_emoji.enabled',
- 'captcha.enabled',
- 'captcha.secret',
- 'captcha.sitekey',
- 'captcha.active.login',
- 'captcha.active.register',
- 'captcha.triggers.login.enabled',
- 'captcha.triggers.login.attempts',
- 'federation.custom_emoji.enabled',
+ 'pixelfed.optimize_image',
+ 'pixelfed.optimize_video',
+ 'pixelfed.max_collection_length',
+ 'media.delete_local_after_cloud',
+ 'instance.user_filters.max_user_blocks',
+ 'instance.user_filters.max_user_mutes',
+ 'instance.user_filters.max_domain_blocks',
- 'pixelfed.optimize_image',
- 'pixelfed.optimize_video',
- 'pixelfed.max_collection_length',
- 'media.delete_local_after_cloud',
- 'instance.user_filters.max_user_blocks',
- 'instance.user_filters.max_user_mutes',
- 'instance.user_filters.max_domain_blocks',
+ 'filesystems.disks.s3.key',
+ 'filesystems.disks.s3.secret',
+ 'filesystems.disks.s3.region',
+ 'filesystems.disks.s3.bucket',
+ 'filesystems.disks.s3.visibility',
+ 'filesystems.disks.s3.url',
+ 'filesystems.disks.s3.endpoint',
+ 'filesystems.disks.s3.use_path_style_endpoint',
- 'filesystems.disks.s3.key',
- 'filesystems.disks.s3.secret',
- 'filesystems.disks.s3.region',
- 'filesystems.disks.s3.bucket',
- 'filesystems.disks.s3.visibility',
- 'filesystems.disks.s3.url',
- 'filesystems.disks.s3.endpoint',
- 'filesystems.disks.s3.use_path_style_endpoint',
+ 'filesystems.disks.spaces.key',
+ 'filesystems.disks.spaces.secret',
+ 'filesystems.disks.spaces.region',
+ 'filesystems.disks.spaces.bucket',
+ 'filesystems.disks.spaces.visibility',
+ 'filesystems.disks.spaces.url',
+ 'filesystems.disks.spaces.endpoint',
+ 'filesystems.disks.spaces.use_path_style_endpoint',
+ // 'system.user_mode'
+ ];
- 'filesystems.disks.spaces.key',
- 'filesystems.disks.spaces.secret',
- 'filesystems.disks.spaces.region',
- 'filesystems.disks.spaces.bucket',
- 'filesystems.disks.spaces.visibility',
- 'filesystems.disks.spaces.url',
- 'filesystems.disks.spaces.endpoint',
- 'filesystems.disks.spaces.use_path_style_endpoint',
- // 'system.user_mode'
- ];
-
- if (! config('instance.enable_cc')) {
- return config($key);
- }
-
- if (! in_array($key, $allowed)) {
- return config($key);
- }
-
- $protect = false;
- $protected = null;
- if(in_array($key, self::PROTECTED_KEYS)) {
- $protect = true;
- }
-
- $v = config($key);
- $c = ConfigCacheModel::where('k', $key)->first();
-
- if ($c) {
- if($protect) {
- return decrypt($c->v) ?? config($key);
- } else {
- return $c->v ?? config($key);
+ if (! config('instance.enable_cc')) {
+ return config($key);
}
- }
- if (! $v) {
- return;
- }
+ if (! in_array($key, $allowed)) {
+ return config($key);
+ }
- if($protect && $v) {
- $protected = encrypt($v);
- }
+ $protect = false;
+ $protected = null;
+ if(in_array($key, self::PROTECTED_KEYS)) {
+ $protect = true;
+ }
- $cc = new ConfigCacheModel;
- $cc->k = $key;
- $cc->v = $protect ? $protected : $v;
- $cc->save();
+ $v = config($key);
+ $c = ConfigCacheModel::where('k', $key)->first();
- return $v;
- });
+ if ($c) {
+ if($protect) {
+ return decrypt($c->v) ?? config($key);
+ } else {
+ return $c->v ?? config($key);
+ }
+ }
+
+ if (! $v) {
+ return;
+ }
+
+ if($protect && $v) {
+ $protected = encrypt($v);
+ }
+
+ $cc = new ConfigCacheModel;
+ $cc->k = $key;
+ $cc->v = $protect ? $protected : $v;
+ $cc->save();
+
+ return $v;
+ });
+ } catch (Exception | QueryException $e) {
+ return config($key);
+ }
}
public static function put($key, $val)
diff --git a/app/Services/CustomEmojiService.php b/app/Services/CustomEmojiService.php
index 468772b5f..f9f267174 100644
--- a/app/Services/CustomEmojiService.php
+++ b/app/Services/CustomEmojiService.php
@@ -133,6 +133,7 @@ class CustomEmojiService
return CustomEmoji::when(!$pgsql, function($q, $pgsql) {
return $q->groupBy('shortcode');
})
+ ->whereNull('uri')
->get()
->map(function($emojo) {
$url = url('storage/' . $emojo->media_path);
diff --git a/composer.lock b/composer.lock
index 3acbe5192..6b4019c3e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -8,16 +8,16 @@
"packages": [
{
"name": "aws/aws-crt-php",
- "version": "v1.2.4",
+ "version": "v1.2.5",
"source": {
"type": "git",
"url": "https://github.com/awslabs/aws-crt-php.git",
- "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2"
+ "reference": "0ea1f04ec5aa9f049f97e012d1ed63b76834a31b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/eb0c6e4e142224a10b08f49ebf87f32611d162b2",
- "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2",
+ "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/0ea1f04ec5aa9f049f97e012d1ed63b76834a31b",
+ "reference": "0ea1f04ec5aa9f049f97e012d1ed63b76834a31b",
"shasum": ""
},
"require": {
@@ -56,22 +56,22 @@
],
"support": {
"issues": "https://github.com/awslabs/aws-crt-php/issues",
- "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.4"
+ "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.5"
},
- "time": "2023-11-08T00:42:13+00:00"
+ "time": "2024-04-19T21:30:56+00:00"
},
{
"name": "aws/aws-sdk-php",
- "version": "3.303.4",
+ "version": "3.306.0",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "9ae5429f7699701cb158780cd287d1549f45ad32"
+ "reference": "dc228b55a4224fe3160a0a2ca430b80c5348d943"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9ae5429f7699701cb158780cd287d1549f45ad32",
- "reference": "9ae5429f7699701cb158780cd287d1549f45ad32",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/dc228b55a4224fe3160a0a2ca430b80c5348d943",
+ "reference": "dc228b55a4224fe3160a0a2ca430b80c5348d943",
"shasum": ""
},
"require": {
@@ -151,9 +151,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
- "source": "https://github.com/aws/aws-sdk-php/tree/3.303.4"
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.306.0"
},
- "time": "2024-04-05T18:04:15+00:00"
+ "time": "2024-05-06T18:11:49+00:00"
},
{
"name": "bacon/bacon-qr-code",
@@ -838,16 +838,16 @@
},
{
"name": "doctrine/dbal",
- "version": "3.8.3",
+ "version": "3.8.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c"
+ "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/db922ba9436b7b18a23d1653a0b41ff2369ca41c",
- "reference": "db922ba9436b7b18a23d1653a0b41ff2369ca41c",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/b05e48a745f722801f55408d0dbd8003b403dbbd",
+ "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd",
"shasum": ""
},
"require": {
@@ -931,7 +931,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/3.8.3"
+ "source": "https://github.com/doctrine/dbal/tree/3.8.4"
},
"funding": [
{
@@ -947,7 +947,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-03T15:55:06+00:00"
+ "time": "2024-04-25T07:04:44+00:00"
},
{
"name": "doctrine/deprecations",
@@ -2369,16 +2369,16 @@
},
{
"name": "jaybizzle/crawler-detect",
- "version": "v1.2.117",
+ "version": "v1.2.118",
"source": {
"type": "git",
"url": "https://github.com/JayBizzle/Crawler-Detect.git",
- "reference": "6785557f03d0fa9e2205352ebae9a12a4484cc8e"
+ "reference": "9b8912ac5b78b780a0ead552b4c3dc9ddfdea4fd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/6785557f03d0fa9e2205352ebae9a12a4484cc8e",
- "reference": "6785557f03d0fa9e2205352ebae9a12a4484cc8e",
+ "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/9b8912ac5b78b780a0ead552b4c3dc9ddfdea4fd",
+ "reference": "9b8912ac5b78b780a0ead552b4c3dc9ddfdea4fd",
"shasum": ""
},
"require": {
@@ -2415,9 +2415,9 @@
],
"support": {
"issues": "https://github.com/JayBizzle/Crawler-Detect/issues",
- "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.117"
+ "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.118"
},
- "time": "2024-03-19T22:51:22+00:00"
+ "time": "2024-04-23T17:07:05+00:00"
},
{
"name": "jenssegers/agent",
@@ -2562,16 +2562,16 @@
},
{
"name": "laravel/framework",
- "version": "v10.48.4",
+ "version": "v10.48.10",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "7e0701bf59cb76a51f7c1f7bea51c0c0c29c0b72"
+ "reference": "91e2b9e218afa4e5c377510faa11957042831ba3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/7e0701bf59cb76a51f7c1f7bea51c0c0c29c0b72",
- "reference": "7e0701bf59cb76a51f7c1f7bea51c0c0c29c0b72",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/91e2b9e218afa4e5c377510faa11957042831ba3",
+ "reference": "91e2b9e218afa4e5c377510faa11957042831ba3",
"shasum": ""
},
"require": {
@@ -2765,7 +2765,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2024-03-21T13:36:36+00:00"
+ "time": "2024-04-30T12:52:59+00:00"
},
{
"name": "laravel/helpers",
@@ -2826,16 +2826,16 @@
},
{
"name": "laravel/horizon",
- "version": "v5.23.2",
+ "version": "v5.24.4",
"source": {
"type": "git",
"url": "https://github.com/laravel/horizon.git",
- "reference": "96d154340f1223bcc161ea7cee355c8fc29ff81e"
+ "reference": "8d31ff178bf5493efc2b2629c10612054f31f584"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/horizon/zipball/96d154340f1223bcc161ea7cee355c8fc29ff81e",
- "reference": "96d154340f1223bcc161ea7cee355c8fc29ff81e",
+ "url": "https://api.github.com/repos/laravel/horizon/zipball/8d31ff178bf5493efc2b2629c10612054f31f584",
+ "reference": "8d31ff178bf5493efc2b2629c10612054f31f584",
"shasum": ""
},
"require": {
@@ -2899,9 +2899,9 @@
],
"support": {
"issues": "https://github.com/laravel/horizon/issues",
- "source": "https://github.com/laravel/horizon/tree/v5.23.2"
+ "source": "https://github.com/laravel/horizon/tree/v5.24.4"
},
- "time": "2024-03-23T12:11:34+00:00"
+ "time": "2024-05-03T13:34:14+00:00"
},
{
"name": "laravel/passport",
@@ -2983,16 +2983,16 @@
},
{
"name": "laravel/prompts",
- "version": "v0.1.17",
+ "version": "v0.1.21",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
- "reference": "8ee9f87f7f9eadcbe21e9e72cd4176b2f06cd5b5"
+ "reference": "23ea808e8a145653e0ab29e30d4385e49f40a920"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/prompts/zipball/8ee9f87f7f9eadcbe21e9e72cd4176b2f06cd5b5",
- "reference": "8ee9f87f7f9eadcbe21e9e72cd4176b2f06cd5b5",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/23ea808e8a145653e0ab29e30d4385e49f40a920",
+ "reference": "23ea808e8a145653e0ab29e30d4385e49f40a920",
"shasum": ""
},
"require": {
@@ -3032,11 +3032,12 @@
"license": [
"MIT"
],
+ "description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
- "source": "https://github.com/laravel/prompts/tree/v0.1.17"
+ "source": "https://github.com/laravel/prompts/tree/v0.1.21"
},
- "time": "2024-03-13T16:05:43+00:00"
+ "time": "2024-04-30T12:46:16+00:00"
},
{
"name": "laravel/serializable-closure",
@@ -3229,34 +3230,34 @@
},
{
"name": "lcobucci/clock",
- "version": "3.0.0",
+ "version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/clock.git",
- "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc"
+ "reference": "6f28b826ea01306b07980cb8320ab30b966cd715"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc",
- "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc",
+ "url": "https://api.github.com/repos/lcobucci/clock/zipball/6f28b826ea01306b07980cb8320ab30b966cd715",
+ "reference": "6f28b826ea01306b07980cb8320ab30b966cd715",
"shasum": ""
},
"require": {
- "php": "~8.1.0 || ~8.2.0",
+ "php": "~8.2.0 || ~8.3.0",
"psr/clock": "^1.0"
},
"provide": {
"psr/clock-implementation": "1.0"
},
"require-dev": {
- "infection/infection": "^0.26",
- "lcobucci/coding-standard": "^9.0",
- "phpstan/extension-installer": "^1.2",
- "phpstan/phpstan": "^1.9.4",
- "phpstan/phpstan-deprecation-rules": "^1.1.1",
- "phpstan/phpstan-phpunit": "^1.3.2",
- "phpstan/phpstan-strict-rules": "^1.4.4",
- "phpunit/phpunit": "^9.5.27"
+ "infection/infection": "^0.27",
+ "lcobucci/coding-standard": "^11.0.0",
+ "phpstan/extension-installer": "^1.3.1",
+ "phpstan/phpstan": "^1.10.25",
+ "phpstan/phpstan-deprecation-rules": "^1.1.3",
+ "phpstan/phpstan-phpunit": "^1.3.13",
+ "phpstan/phpstan-strict-rules": "^1.5.1",
+ "phpunit/phpunit": "^10.2.3"
},
"type": "library",
"autoload": {
@@ -3277,7 +3278,7 @@
"description": "Yet another clock abstraction",
"support": {
"issues": "https://github.com/lcobucci/clock/issues",
- "source": "https://github.com/lcobucci/clock/tree/3.0.0"
+ "source": "https://github.com/lcobucci/clock/tree/3.2.0"
},
"funding": [
{
@@ -3289,20 +3290,20 @@
"type": "patreon"
}
],
- "time": "2022-12-19T15:00:24+00:00"
+ "time": "2023-11-17T17:00:27+00:00"
},
{
"name": "lcobucci/jwt",
- "version": "5.2.0",
+ "version": "5.3.0",
"source": {
"type": "git",
"url": "https://github.com/lcobucci/jwt.git",
- "reference": "0ba88aed12c04bd2ed9924f500673f32b67a6211"
+ "reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0ba88aed12c04bd2ed9924f500673f32b67a6211",
- "reference": "0ba88aed12c04bd2ed9924f500673f32b67a6211",
+ "url": "https://api.github.com/repos/lcobucci/jwt/zipball/08071d8d2c7f4b00222cc4b1fb6aa46990a80f83",
+ "reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83",
"shasum": ""
},
"require": {
@@ -3350,7 +3351,7 @@
],
"support": {
"issues": "https://github.com/lcobucci/jwt/issues",
- "source": "https://github.com/lcobucci/jwt/tree/5.2.0"
+ "source": "https://github.com/lcobucci/jwt/tree/5.3.0"
},
"funding": [
{
@@ -3362,7 +3363,7 @@
"type": "patreon"
}
],
- "time": "2023-11-20T21:17:42+00:00"
+ "time": "2024-04-11T23:07:54+00:00"
},
{
"name": "league/commonmark",
@@ -3608,16 +3609,16 @@
},
{
"name": "league/flysystem",
- "version": "3.26.0",
+ "version": "3.27.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
- "reference": "072735c56cc0da00e10716dd90d5a7f7b40b36be"
+ "reference": "4729745b1ab737908c7d055148c9a6b3e959832f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/072735c56cc0da00e10716dd90d5a7f7b40b36be",
- "reference": "072735c56cc0da00e10716dd90d5a7f7b40b36be",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4729745b1ab737908c7d055148c9a6b3e959832f",
+ "reference": "4729745b1ab737908c7d055148c9a6b3e959832f",
"shasum": ""
},
"require": {
@@ -3682,7 +3683,7 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
- "source": "https://github.com/thephpleague/flysystem/tree/3.26.0"
+ "source": "https://github.com/thephpleague/flysystem/tree/3.27.0"
},
"funding": [
{
@@ -3694,20 +3695,20 @@
"type": "github"
}
],
- "time": "2024-03-25T11:49:53+00:00"
+ "time": "2024-04-07T19:17:50+00:00"
},
{
"name": "league/flysystem-aws-s3-v3",
- "version": "3.26.0",
+ "version": "3.27.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
- "reference": "885d0a758c71ae3cd6c503544573a1fdb8dc754f"
+ "reference": "3e6ce2f972f1470db779f04d29c289dcd2c32837"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/885d0a758c71ae3cd6c503544573a1fdb8dc754f",
- "reference": "885d0a758c71ae3cd6c503544573a1fdb8dc754f",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/3e6ce2f972f1470db779f04d29c289dcd2c32837",
+ "reference": "3e6ce2f972f1470db779f04d29c289dcd2c32837",
"shasum": ""
},
"require": {
@@ -3747,7 +3748,7 @@
"storage"
],
"support": {
- "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.26.0"
+ "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.27.0"
},
"funding": [
{
@@ -3759,7 +3760,7 @@
"type": "github"
}
],
- "time": "2024-03-24T21:11:18+00:00"
+ "time": "2024-04-07T19:16:54+00:00"
},
{
"name": "league/flysystem-local",
@@ -4327,16 +4328,16 @@
},
{
"name": "monolog/monolog",
- "version": "3.5.0",
+ "version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448"
+ "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448",
- "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654",
+ "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654",
"shasum": ""
},
"require": {
@@ -4359,7 +4360,7 @@
"phpstan/phpstan": "^1.9",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-strict-rules": "^1.4",
- "phpunit/phpunit": "^10.1",
+ "phpunit/phpunit": "^10.5.17",
"predis/predis": "^1.1 || ^2",
"ruflin/elastica": "^7",
"symfony/mailer": "^5.4 || ^6",
@@ -4412,7 +4413,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
- "source": "https://github.com/Seldaek/monolog/tree/3.5.0"
+ "source": "https://github.com/Seldaek/monolog/tree/3.6.0"
},
"funding": [
{
@@ -4424,7 +4425,7 @@
"type": "tidelift"
}
],
- "time": "2023-10-27T15:32:31+00:00"
+ "time": "2024-04-12T21:02:21+00:00"
},
{
"name": "mtdowling/jmespath.php",
@@ -5088,16 +5089,16 @@
},
{
"name": "paragonie/sodium_compat",
- "version": "v1.20.1",
+ "version": "v1.21.1",
"source": {
"type": "git",
"url": "https://github.com/paragonie/sodium_compat.git",
- "reference": "1840b98d228bdad83869b191d7e51f9bb6624d8d"
+ "reference": "bb312875dcdd20680419564fe42ba1d9564b9e37"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/1840b98d228bdad83869b191d7e51f9bb6624d8d",
- "reference": "1840b98d228bdad83869b191d7e51f9bb6624d8d",
+ "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/bb312875dcdd20680419564fe42ba1d9564b9e37",
+ "reference": "bb312875dcdd20680419564fe42ba1d9564b9e37",
"shasum": ""
},
"require": {
@@ -5168,9 +5169,9 @@
],
"support": {
"issues": "https://github.com/paragonie/sodium_compat/issues",
- "source": "https://github.com/paragonie/sodium_compat/tree/v1.20.1"
+ "source": "https://github.com/paragonie/sodium_compat/tree/v1.21.1"
},
- "time": "2024-04-05T21:00:10+00:00"
+ "time": "2024-04-22T22:05:04+00:00"
},
{
"name": "pbmedia/laravel-ffmpeg",
@@ -6548,20 +6549,20 @@
},
{
"name": "ramsey/uuid",
- "version": "4.7.5",
+ "version": "4.7.6",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
- "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
+ "reference": "91039bc1faa45ba123c4328958e620d382ec7088"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
- "reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088",
+ "reference": "91039bc1faa45ba123c4328958e620d382ec7088",
"shasum": ""
},
"require": {
- "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11",
+ "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12",
"ext-json": "*",
"php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0"
@@ -6624,7 +6625,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
- "source": "https://github.com/ramsey/uuid/tree/4.7.5"
+ "source": "https://github.com/ramsey/uuid/tree/4.7.6"
},
"funding": [
{
@@ -6636,7 +6637,7 @@
"type": "tidelift"
}
],
- "time": "2023-11-08T05:53:05+00:00"
+ "time": "2024-04-27T21:32:50+00:00"
},
{
"name": "ratchet/rfc6455",
@@ -7239,16 +7240,16 @@
},
{
"name": "spatie/db-dumper",
- "version": "3.4.3",
+ "version": "3.6.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/db-dumper.git",
- "reference": "c566852826f3e9dceea27eef5173bad93b83e61c"
+ "reference": "faca5056830bccea04eadf07e8074669cb9e905e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/db-dumper/zipball/c566852826f3e9dceea27eef5173bad93b83e61c",
- "reference": "c566852826f3e9dceea27eef5173bad93b83e61c",
+ "url": "https://api.github.com/repos/spatie/db-dumper/zipball/faca5056830bccea04eadf07e8074669cb9e905e",
+ "reference": "faca5056830bccea04eadf07e8074669cb9e905e",
"shasum": ""
},
"require": {
@@ -7286,7 +7287,7 @@
"spatie"
],
"support": {
- "source": "https://github.com/spatie/db-dumper/tree/3.4.3"
+ "source": "https://github.com/spatie/db-dumper/tree/3.6.0"
},
"funding": [
{
@@ -7298,20 +7299,20 @@
"type": "github"
}
],
- "time": "2024-04-01T07:37:06+00:00"
+ "time": "2024-04-24T14:54:13+00:00"
},
{
"name": "spatie/image-optimizer",
- "version": "1.7.2",
+ "version": "1.7.4",
"source": {
"type": "git",
"url": "https://github.com/spatie/image-optimizer.git",
- "reference": "62f7463483d1bd975f6f06025d89d42a29608fe1"
+ "reference": "ed39c7bfce7a2ecf676174a2d4286ab3a1c4f4f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/62f7463483d1bd975f6f06025d89d42a29608fe1",
- "reference": "62f7463483d1bd975f6f06025d89d42a29608fe1",
+ "url": "https://api.github.com/repos/spatie/image-optimizer/zipball/ed39c7bfce7a2ecf676174a2d4286ab3a1c4f4f7",
+ "reference": "ed39c7bfce7a2ecf676174a2d4286ab3a1c4f4f7",
"shasum": ""
},
"require": {
@@ -7351,22 +7352,22 @@
],
"support": {
"issues": "https://github.com/spatie/image-optimizer/issues",
- "source": "https://github.com/spatie/image-optimizer/tree/1.7.2"
+ "source": "https://github.com/spatie/image-optimizer/tree/1.7.4"
},
- "time": "2023-11-03T10:08:02+00:00"
+ "time": "2024-05-06T09:12:30+00:00"
},
{
"name": "spatie/laravel-backup",
- "version": "8.6.0",
+ "version": "8.8.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-backup.git",
- "reference": "c6a7607c0eea80efc2cf6628ffcd172f73a2088f"
+ "reference": "7e74431fc5c46319a27daa44897df1c7bf4afe5a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/c6a7607c0eea80efc2cf6628ffcd172f73a2088f",
- "reference": "c6a7607c0eea80efc2cf6628ffcd172f73a2088f",
+ "url": "https://api.github.com/repos/spatie/laravel-backup/zipball/7e74431fc5c46319a27daa44897df1c7bf4afe5a",
+ "reference": "7e74431fc5c46319a27daa44897df1c7bf4afe5a",
"shasum": ""
},
"require": {
@@ -7440,7 +7441,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-backup/issues",
- "source": "https://github.com/spatie/laravel-backup/tree/8.6.0"
+ "source": "https://github.com/spatie/laravel-backup/tree/8.8.0"
},
"funding": [
{
@@ -7452,7 +7453,7 @@
"type": "other"
}
],
- "time": "2024-02-06T20:39:11+00:00"
+ "time": "2024-05-02T13:09:01+00:00"
},
{
"name": "spatie/laravel-image-optimizer",
@@ -7850,31 +7851,31 @@
},
{
"name": "symfony/cache",
- "version": "v6.4.6",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
- "reference": "b59bbf9c093b592d77110f9ee70c74dff89294cb"
+ "reference": "48e3508338987d63b0114a00c208c4cbb76e5303"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache/zipball/b59bbf9c093b592d77110f9ee70c74dff89294cb",
- "reference": "b59bbf9c093b592d77110f9ee70c74dff89294cb",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/48e3508338987d63b0114a00c208c4cbb76e5303",
+ "reference": "48e3508338987d63b0114a00c208c4cbb76e5303",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"psr/cache": "^2.0|^3.0",
"psr/log": "^1.1|^2|^3",
"symfony/cache-contracts": "^2.5|^3",
"symfony/service-contracts": "^2.5|^3",
- "symfony/var-exporter": "^6.3.6|^7.0"
+ "symfony/var-exporter": "^6.4|^7.0"
},
"conflict": {
- "doctrine/dbal": "<2.13.1",
- "symfony/dependency-injection": "<5.4",
- "symfony/http-kernel": "<5.4",
- "symfony/var-dumper": "<5.4"
+ "doctrine/dbal": "<3.6",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/var-dumper": "<6.4"
},
"provide": {
"psr/cache-implementation": "2.0|3.0",
@@ -7883,15 +7884,15 @@
},
"require-dev": {
"cache/integration-tests": "dev-master",
- "doctrine/dbal": "^2.13.1|^3|^4",
+ "doctrine/dbal": "^3.6|^4",
"predis/predis": "^1.1|^2.0",
"psr/simple-cache": "^1.0|^2.0|^3.0",
- "symfony/config": "^5.4|^6.0|^7.0",
- "symfony/dependency-injection": "^5.4|^6.0|^7.0",
- "symfony/filesystem": "^5.4|^6.0|^7.0",
- "symfony/http-kernel": "^5.4|^6.0|^7.0",
- "symfony/messenger": "^5.4|^6.0|^7.0",
- "symfony/var-dumper": "^5.4|^6.0|^7.0"
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -7926,7 +7927,7 @@
"psr6"
],
"support": {
- "source": "https://github.com/symfony/cache/tree/v6.4.6"
+ "source": "https://github.com/symfony/cache/tree/v7.0.7"
},
"funding": [
{
@@ -7942,20 +7943,20 @@
"type": "tidelift"
}
],
- "time": "2024-03-27T13:27:42+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/cache-contracts",
- "version": "v3.4.2",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache-contracts.git",
- "reference": "2c9db6509a1b21dad229606897639d3284f54b2a"
+ "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/2c9db6509a1b21dad229606897639d3284f54b2a",
- "reference": "2c9db6509a1b21dad229606897639d3284f54b2a",
+ "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197",
+ "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197",
"shasum": ""
},
"require": {
@@ -7965,7 +7966,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -8002,7 +8003,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/cache-contracts/tree/v3.4.2"
+ "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -8018,20 +8019,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/console",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "a2708a5da5c87d1d0d52937bdeac625df659e11f"
+ "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/a2708a5da5c87d1d0d52937bdeac625df659e11f",
- "reference": "a2708a5da5c87d1d0d52937bdeac625df659e11f",
+ "url": "https://api.github.com/repos/symfony/console/zipball/a170e64ae10d00ba89e2acbb590dc2e54da8ad8f",
+ "reference": "a170e64ae10d00ba89e2acbb590dc2e54da8ad8f",
"shasum": ""
},
"require": {
@@ -8096,7 +8097,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.4.6"
+ "source": "https://github.com/symfony/console/tree/v6.4.7"
},
"funding": [
{
@@ -8112,24 +8113,24 @@
"type": "tidelift"
}
],
- "time": "2024-03-29T19:07:53+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v6.4.3",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229"
+ "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/ee0f7ed5cf298cc019431bb3b3977ebc52b86229",
- "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc",
+ "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.2"
},
"type": "library",
"autoload": {
@@ -8161,7 +8162,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v6.4.3"
+ "source": "https://github.com/symfony/css-selector/tree/v7.0.7"
},
"funding": [
{
@@ -8177,20 +8178,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.4.0",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
+ "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
- "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
+ "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"shasum": ""
},
"require": {
@@ -8199,7 +8200,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -8228,7 +8229,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -8244,20 +8245,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-23T14:45:45+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/error-handler",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "64db1c1802e3a4557e37ba33031ac39f452ac5d4"
+ "reference": "667a072466c6a53827ed7b119af93806b884cbb3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/64db1c1802e3a4557e37ba33031ac39f452ac5d4",
- "reference": "64db1c1802e3a4557e37ba33031ac39f452ac5d4",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/667a072466c6a53827ed7b119af93806b884cbb3",
+ "reference": "667a072466c6a53827ed7b119af93806b884cbb3",
"shasum": ""
},
"require": {
@@ -8303,7 +8304,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v6.4.6"
+ "source": "https://github.com/symfony/error-handler/tree/v6.4.7"
},
"funding": [
{
@@ -8319,28 +8320,28 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T11:56:30+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v6.4.3",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef"
+ "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ae9d3a6f3003a6caf56acd7466d8d52378d44fef",
- "reference": "ae9d3a6f3003a6caf56acd7466d8d52378d44fef",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db2a7fab994d67d92356bb39c367db115d9d30f9",
+ "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/dependency-injection": "<5.4",
+ "symfony/dependency-injection": "<6.4",
"symfony/service-contracts": "<2.5"
},
"provide": {
@@ -8349,13 +8350,13 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^5.4|^6.0|^7.0",
- "symfony/dependency-injection": "^5.4|^6.0|^7.0",
- "symfony/error-handler": "^5.4|^6.0|^7.0",
- "symfony/expression-language": "^5.4|^6.0|^7.0",
- "symfony/http-foundation": "^5.4|^6.0|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^5.4|^6.0|^7.0"
+ "symfony/stopwatch": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -8383,7 +8384,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.3"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.7"
},
"funding": [
{
@@ -8399,20 +8400,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
- "version": "v3.4.2",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
- "reference": "4e64b49bf370ade88e567de29465762e316e4224"
+ "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224",
- "reference": "4e64b49bf370ade88e567de29465762e316e4224",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50",
+ "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50",
"shasum": ""
},
"require": {
@@ -8422,7 +8423,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -8459,7 +8460,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2"
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -8475,20 +8476,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/finder",
- "version": "v6.4.0",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "11d736e97f116ac375a81f96e662911a34cd50ce"
+ "reference": "511c48990be17358c23bf45c5d71ab85d40fb764"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce",
- "reference": "11d736e97f116ac375a81f96e662911a34cd50ce",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/511c48990be17358c23bf45c5d71ab85d40fb764",
+ "reference": "511c48990be17358c23bf45c5d71ab85d40fb764",
"shasum": ""
},
"require": {
@@ -8523,7 +8524,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v6.4.0"
+ "source": "https://github.com/symfony/finder/tree/v6.4.7"
},
"funding": [
{
@@ -8539,20 +8540,20 @@
"type": "tidelift"
}
],
- "time": "2023-10-31T17:30:12+00:00"
+ "time": "2024-04-23T10:36:43+00:00"
},
{
"name": "symfony/http-client",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
- "reference": "6a46c0ea9b099f9a5132d560a51833ffcbd5b0d9"
+ "reference": "3683d8107cf1efdd24795cc5f7482be1eded34ac"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client/zipball/6a46c0ea9b099f9a5132d560a51833ffcbd5b0d9",
- "reference": "6a46c0ea9b099f9a5132d560a51833ffcbd5b0d9",
+ "url": "https://api.github.com/repos/symfony/http-client/zipball/3683d8107cf1efdd24795cc5f7482be1eded34ac",
+ "reference": "3683d8107cf1efdd24795cc5f7482be1eded34ac",
"shasum": ""
},
"require": {
@@ -8616,7 +8617,7 @@
"http"
],
"support": {
- "source": "https://github.com/symfony/http-client/tree/v6.4.6"
+ "source": "https://github.com/symfony/http-client/tree/v6.4.7"
},
"funding": [
{
@@ -8632,20 +8633,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-01T20:35:50+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/http-client-contracts",
- "version": "v3.4.2",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client-contracts.git",
- "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e"
+ "reference": "20414d96f391677bf80078aa55baece78b82647d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e",
- "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e",
+ "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d",
+ "reference": "20414d96f391677bf80078aa55baece78b82647d",
"shasum": ""
},
"require": {
@@ -8654,7 +8655,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -8694,7 +8695,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.2"
+ "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -8710,20 +8711,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-01T18:51:09+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v6.4.4",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304"
+ "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ebc713bc6e6f4b53f46539fc158be85dfcd77304",
- "reference": "ebc713bc6e6f4b53f46539fc158be85dfcd77304",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b4db6b833035477cb70e18d0ae33cb7c2b521759",
+ "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759",
"shasum": ""
},
"require": {
@@ -8771,7 +8772,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v6.4.4"
+ "source": "https://github.com/symfony/http-foundation/tree/v6.4.7"
},
"funding": [
{
@@ -8787,20 +8788,20 @@
"type": "tidelift"
}
],
- "time": "2024-02-08T15:01:18+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "060038863743fd0cd982be06acecccf246d35653"
+ "reference": "b7b5e6cdef670a0c82d015a966ffc7e855861a98"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/060038863743fd0cd982be06acecccf246d35653",
- "reference": "060038863743fd0cd982be06acecccf246d35653",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b7b5e6cdef670a0c82d015a966ffc7e855861a98",
+ "reference": "b7b5e6cdef670a0c82d015a966ffc7e855861a98",
"shasum": ""
},
"require": {
@@ -8855,6 +8856,7 @@
"symfony/translation-contracts": "^2.5|^3",
"symfony/uid": "^5.4|^6.0|^7.0",
"symfony/validator": "^6.4|^7.0",
+ "symfony/var-dumper": "^5.4|^6.4|^7.0",
"symfony/var-exporter": "^6.2|^7.0",
"twig/twig": "^2.13|^3.0.4"
},
@@ -8884,7 +8886,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v6.4.6"
+ "source": "https://github.com/symfony/http-kernel/tree/v6.4.7"
},
"funding": [
{
@@ -8900,20 +8902,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-03T06:09:15+00:00"
+ "time": "2024-04-29T11:24:44+00:00"
},
{
"name": "symfony/mailer",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "677f34a6f4b4559e08acf73ae0aec460479e5859"
+ "reference": "2c446d4e446995bed983c0b5bb9ff837e8de7dbd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/677f34a6f4b4559e08acf73ae0aec460479e5859",
- "reference": "677f34a6f4b4559e08acf73ae0aec460479e5859",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/2c446d4e446995bed983c0b5bb9ff837e8de7dbd",
+ "reference": "2c446d4e446995bed983c0b5bb9ff837e8de7dbd",
"shasum": ""
},
"require": {
@@ -8964,7 +8966,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v6.4.6"
+ "source": "https://github.com/symfony/mailer/tree/v6.4.7"
},
"funding": [
{
@@ -8980,20 +8982,20 @@
"type": "tidelift"
}
],
- "time": "2024-03-27T21:14:17+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/mailgun-mailer",
- "version": "v6.4.4",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailgun-mailer.git",
- "reference": "8c018872b40ce050590b6d18cf741db0c8313435"
+ "reference": "044eede71c3eb5fbe7192042b8c0d04987b5653d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/8c018872b40ce050590b6d18cf741db0c8313435",
- "reference": "8c018872b40ce050590b6d18cf741db0c8313435",
+ "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/044eede71c3eb5fbe7192042b8c0d04987b5653d",
+ "reference": "044eede71c3eb5fbe7192042b8c0d04987b5653d",
"shasum": ""
},
"require": {
@@ -9033,7 +9035,7 @@
"description": "Symfony Mailgun Mailer Bridge",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailgun-mailer/tree/v6.4.4"
+ "source": "https://github.com/symfony/mailgun-mailer/tree/v6.4.7"
},
"funding": [
{
@@ -9049,20 +9051,20 @@
"type": "tidelift"
}
],
- "time": "2024-02-14T06:31:46+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/mime",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "14762b86918823cb42e3558cdcca62e58b5227fe"
+ "reference": "decadcf3865918ecfcbfa90968553994ce935a5e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/14762b86918823cb42e3558cdcca62e58b5227fe",
- "reference": "14762b86918823cb42e3558cdcca62e58b5227fe",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/decadcf3865918ecfcbfa90968553994ce935a5e",
+ "reference": "decadcf3865918ecfcbfa90968553994ce935a5e",
"shasum": ""
},
"require": {
@@ -9118,7 +9120,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v6.4.6"
+ "source": "https://github.com/symfony/mime/tree/v6.4.7"
},
"funding": [
{
@@ -9134,7 +9136,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-21T19:36:20+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -9849,16 +9851,16 @@
},
{
"name": "symfony/process",
- "version": "v6.4.4",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "710e27879e9be3395de2b98da3f52a946039f297"
+ "reference": "cdb1c81c145fd5aa9b0038bab694035020943381"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/710e27879e9be3395de2b98da3f52a946039f297",
- "reference": "710e27879e9be3395de2b98da3f52a946039f297",
+ "url": "https://api.github.com/repos/symfony/process/zipball/cdb1c81c145fd5aa9b0038bab694035020943381",
+ "reference": "cdb1c81c145fd5aa9b0038bab694035020943381",
"shasum": ""
},
"require": {
@@ -9890,7 +9892,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v6.4.4"
+ "source": "https://github.com/symfony/process/tree/v6.4.7"
},
"funding": [
{
@@ -9906,7 +9908,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-20T12:31:00+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
@@ -9999,16 +10001,16 @@
},
{
"name": "symfony/routing",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "f2591fd1f8c6e3734656b5d6b3829e8bf81f507c"
+ "reference": "276e06398f71fa2a973264d94f28150f93cfb907"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/f2591fd1f8c6e3734656b5d6b3829e8bf81f507c",
- "reference": "f2591fd1f8c6e3734656b5d6b3829e8bf81f507c",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/276e06398f71fa2a973264d94f28150f93cfb907",
+ "reference": "276e06398f71fa2a973264d94f28150f93cfb907",
"shasum": ""
},
"require": {
@@ -10062,7 +10064,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v6.4.6"
+ "source": "https://github.com/symfony/routing/tree/v6.4.7"
},
"funding": [
{
@@ -10078,25 +10080,26 @@
"type": "tidelift"
}
],
- "time": "2024-03-28T13:28:49+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.4.2",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "11bbf19a0fb7b36345861e85c5768844c552906e"
+ "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e",
- "reference": "11bbf19a0fb7b36345861e85c5768844c552906e",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
+ "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f",
"shasum": ""
},
"require": {
"php": ">=8.1",
- "psr/container": "^1.1|^2.0"
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"ext-psr": "<1.1|>=2"
@@ -10104,7 +10107,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -10144,7 +10147,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.4.2"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -10160,24 +10163,24 @@
"type": "tidelift"
}
],
- "time": "2023-12-19T21:51:00+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/string",
- "version": "v6.4.4",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9"
+ "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9",
- "reference": "4e465a95bdc32f49cf4c7f07f751b843bbd6dcd9",
+ "url": "https://api.github.com/repos/symfony/string/zipball/e405b5424dc2528e02e31ba26b83a79fd4eb8f63",
+ "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
@@ -10187,11 +10190,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/error-handler": "^5.4|^6.0|^7.0",
- "symfony/http-client": "^5.4|^6.0|^7.0",
- "symfony/intl": "^6.2|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^5.4|^6.0|^7.0"
+ "symfony/var-exporter": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -10230,7 +10233,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.4.4"
+ "source": "https://github.com/symfony/string/tree/v7.0.7"
},
"funding": [
{
@@ -10246,20 +10249,20 @@
"type": "tidelift"
}
],
- "time": "2024-02-01T13:16:41+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "symfony/translation",
- "version": "v6.4.4",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e"
+ "reference": "7495687c58bfd88b7883823747b0656d90679123"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/bce6a5a78e94566641b2594d17e48b0da3184a8e",
- "reference": "bce6a5a78e94566641b2594d17e48b0da3184a8e",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/7495687c58bfd88b7883823747b0656d90679123",
+ "reference": "7495687c58bfd88b7883823747b0656d90679123",
"shasum": ""
},
"require": {
@@ -10325,7 +10328,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v6.4.4"
+ "source": "https://github.com/symfony/translation/tree/v6.4.7"
},
"funding": [
{
@@ -10341,20 +10344,20 @@
"type": "tidelift"
}
],
- "time": "2024-02-20T13:16:58+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/translation-contracts",
- "version": "v3.4.2",
+ "version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
- "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b"
+ "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/43810bdb2ddb5400e5c5e778e27b210a0ca83b6b",
- "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a",
+ "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a",
"shasum": ""
},
"require": {
@@ -10363,7 +10366,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
+ "dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -10403,7 +10406,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v3.4.2"
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0"
},
"funding": [
{
@@ -10419,20 +10422,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/uid",
- "version": "v6.4.3",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/uid.git",
- "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0"
+ "reference": "a66efcb71d8bc3a207d9d78e0bd67f3321510355"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/uid/zipball/1d31267211cc3a2fff32bcfc7c1818dac41b6fc0",
- "reference": "1d31267211cc3a2fff32bcfc7c1818dac41b6fc0",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/a66efcb71d8bc3a207d9d78e0bd67f3321510355",
+ "reference": "a66efcb71d8bc3a207d9d78e0bd67f3321510355",
"shasum": ""
},
"require": {
@@ -10477,7 +10480,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/uid/tree/v6.4.3"
+ "source": "https://github.com/symfony/uid/tree/v6.4.7"
},
"funding": [
{
@@ -10493,20 +10496,20 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T14:51:35+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v6.4.6",
+ "version": "v6.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "95bd2706a97fb875185b51ecaa6112ec184233d4"
+ "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/95bd2706a97fb875185b51ecaa6112ec184233d4",
- "reference": "95bd2706a97fb875185b51ecaa6112ec184233d4",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7a9cd977cd1c5fed3694bee52990866432af07d7",
+ "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7",
"shasum": ""
},
"require": {
@@ -10562,7 +10565,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v6.4.6"
+ "source": "https://github.com/symfony/var-dumper/tree/v6.4.7"
},
"funding": [
{
@@ -10578,30 +10581,29 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T11:56:30+00:00"
+ "time": "2024-04-18T09:22:46+00:00"
},
{
"name": "symfony/var-exporter",
- "version": "v6.4.6",
+ "version": "v7.0.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
- "reference": "20888cf4d11de203613515cf0587828bf5af0fe7"
+ "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-exporter/zipball/20888cf4d11de203613515cf0587828bf5af0fe7",
- "reference": "20888cf4d11de203613515cf0587828bf5af0fe7",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/cdecc0022e40e90340ba1a59a3d5ccf069777078",
+ "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "symfony/deprecation-contracts": "^2.5|^3"
+ "php": ">=8.2"
},
"require-dev": {
"symfony/property-access": "^6.4|^7.0",
"symfony/serializer": "^6.4|^7.0",
- "symfony/var-dumper": "^5.4|^6.0|^7.0"
+ "symfony/var-dumper": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -10639,7 +10641,7 @@
"serialize"
],
"support": {
- "source": "https://github.com/symfony/var-exporter/tree/v6.4.6"
+ "source": "https://github.com/symfony/var-exporter/tree/v7.0.7"
},
"funding": [
{
@@ -10655,7 +10657,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-20T21:07:14+00:00"
+ "time": "2024-04-18T09:29:19+00:00"
},
{
"name": "tightenco/collect",
@@ -11831,16 +11833,16 @@
},
{
"name": "laravel/pint",
- "version": "v1.15.1",
+ "version": "v1.15.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
- "reference": "5f288b5e79938cc72f5c298d384e639de87507c6"
+ "reference": "3600b5d17aff52f6100ea4921849deacbbeb8656"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/5f288b5e79938cc72f5c298d384e639de87507c6",
- "reference": "5f288b5e79938cc72f5c298d384e639de87507c6",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/3600b5d17aff52f6100ea4921849deacbbeb8656",
+ "reference": "3600b5d17aff52f6100ea4921849deacbbeb8656",
"shasum": ""
},
"require": {
@@ -11851,13 +11853,13 @@
"php": "^8.1.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.52.1",
- "illuminate/view": "^10.48.4",
- "larastan/larastan": "^2.9.2",
+ "friendsofphp/php-cs-fixer": "^3.54.0",
+ "illuminate/view": "^10.48.8",
+ "larastan/larastan": "^2.9.5",
"laravel-zero/framework": "^10.3.0",
"mockery/mockery": "^1.6.11",
"nunomaduro/termwind": "^1.15.1",
- "pestphp/pest": "^2.34.5"
+ "pestphp/pest": "^2.34.7"
},
"bin": [
"builds/pint"
@@ -11893,7 +11895,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2024-04-02T14:28:47+00:00"
+ "time": "2024-04-30T15:02:26+00:00"
},
{
"name": "laravel/telescope",
diff --git a/config/pixelfed.php b/config/pixelfed.php
index 9da274434..c4dc5828b 100644
--- a/config/pixelfed.php
+++ b/config/pixelfed.php
@@ -23,7 +23,7 @@ return [
| This value is the version of your Pixelfed instance.
|
*/
- 'version' => '0.11.13',
+ 'version' => '0.12.1',
/*
|--------------------------------------------------------------------------
diff --git a/public/embed.js b/public/embed.js
index 5acc20efe..ab7f9a539 100644
Binary files a/public/embed.js and b/public/embed.js differ
diff --git a/resources/assets/components/partials/post/PostContent.vue b/resources/assets/components/partials/post/PostContent.vue
index 0a88acb19..9672d52e9 100644
--- a/resources/assets/components/partials/post/PostContent.vue
+++ b/resources/assets/components/partials/post/PostContent.vue
@@ -169,7 +169,7 @@
diff --git a/resources/assets/components/presenter/PhotoAlbumPresenter.vue b/resources/assets/components/presenter/PhotoAlbumPresenter.vue
new file mode 100644
index 000000000..3adda10df
--- /dev/null
+++ b/resources/assets/components/presenter/PhotoAlbumPresenter.vue
@@ -0,0 +1,188 @@
+
+
+
+
+ Sensitive Content
+
+ {{ status.spoiler_text ? status.spoiler_text : 'This album may contain sensitive content.'}}
+
+
+
+
+
+ Sensitive Content
+
+ {{ status.spoiler_text ? status.spoiler_text : 'This post may contain sensitive content.'}}
+
+
+
+
+ Photo by @{{status.account.username}} licensed under {{status.media_attachments[0].license.title}} {{ status.spoiler_text ? status.spoiler_text : 'CW / NSFW / Hidden Media'}} (click to show)
+
+
+ Sensitive Content
+
+ {{ status.spoiler_text ? status.spoiler_text : 'This post may contain sensitive content.'}}
+
+
+
+
+