From bc2791fb4968581b61db4f3f70967976e1b71301 Mon Sep 17 00:00:00 2001 From: Austin Kregel <5355937+austinkregel@users.noreply.github.com> Date: Fri, 31 May 2024 21:38:24 -0400 Subject: [PATCH 01/36] wip --- .../Documents/PdfParserServiceContract.php | 11 + .../Spork/LocalAdminController.php | 10 +- app/Http/Middleware/HandleInertiaRequests.php | 4 +- .../BuildSummaryNotificationJob.php | 1 + app/Jobs/SyncMailboxIfCredentialsAreSet.php | 2 + app/Models/ExternalRssFeed.php | 2 +- app/Models/Finance/Account.php | 6 + app/Models/Finance/Transaction.php | 5 +- app/Models/Tag.php | 2 + .../Daily/SummaryNotification.php | 2 + app/Providers/AppServiceProvider.php | 3 + app/Services/ConditionService.php | 14 +- .../Development/DescribeTableService.php | 12 +- app/Services/Documents/MenuCardParser.php | 178 +++++++++++ app/Services/Documents/PdfParserService.php | 68 ++++ app/Services/Documents/PdfReaderService.php | 43 +++ composer.json | 2 + composer.lock | 293 +++++++++++++++--- ...0807_add_priority_to_dns_records_table.php | 28 ++ docker/base/Dockerfile | 2 +- resources/js/Components/Modal.vue | 18 +- .../Spork/Atoms/NotificationMessage.vue | 34 ++ .../Spork/Atoms/NotificationToast.vue | 32 ++ .../Spork/Atoms/NotificationWithAction.vue | 35 +++ resources/js/Components/Spork/CrudView.vue | 121 ++++---- .../Spork/Molecules/ApplyTagModal.vue | 105 +++++++ .../Notifications/SummaryNotification.vue | 6 + .../js/Components/Spork/SporkDynamicInput.vue | 4 +- resources/js/Components/Spork/SporkTable.vue | 12 +- resources/js/Layouts/AppLayout.vue | 12 +- resources/js/Layouts/Manage.vue | 1 + resources/js/Pages/Manage/Index.vue | 55 +++- resources/js/Pages/Notifications.vue | 67 ++++ resources/js/Pages/Postal/Inbox.vue | 23 +- resources/js/Pages/Postal/Index.vue | 2 +- resources/js/app.js | 10 + routes/crud.php | 1 + routes/pages/spork.php | 3 + routes/web.php | 1 + 39 files changed, 1060 insertions(+), 170 deletions(-) create mode 100644 app/Contracts/Services/Documents/PdfParserServiceContract.php create mode 100644 app/Services/Documents/MenuCardParser.php create mode 100644 app/Services/Documents/PdfParserService.php create mode 100644 app/Services/Documents/PdfReaderService.php create mode 100644 database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php create mode 100644 resources/js/Components/Spork/Atoms/NotificationMessage.vue create mode 100644 resources/js/Components/Spork/Atoms/NotificationToast.vue create mode 100644 resources/js/Components/Spork/Atoms/NotificationWithAction.vue create mode 100644 resources/js/Components/Spork/Molecules/ApplyTagModal.vue create mode 100644 resources/js/Components/Spork/Molecules/Notifications/SummaryNotification.vue create mode 100644 resources/js/Pages/Notifications.vue diff --git a/app/Contracts/Services/Documents/PdfParserServiceContract.php b/app/Contracts/Services/Documents/PdfParserServiceContract.php new file mode 100644 index 00000000..a4882d03 --- /dev/null +++ b/app/Contracts/Services/Documents/PdfParserServiceContract.php @@ -0,0 +1,11 @@ +getModel($request); + $abstractEloquentModel = $modelClass::findOrFail($abstractEloquentModel); + $abstractEloquentModel->delete(); + + return response('', 204); + } public function forceDestroy(ForceDeleteRequest $request, $abstractEloquentModel) { @@ -154,7 +162,7 @@ public function forceDestroy(ForceDeleteRequest $request, $abstractEloquentModel return; } - $abstractEloquentModel->forceDelete(); + $abstractEldoquentModel->forceDelete(); return response('', 204); } diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 6395e622..1ba50905 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -40,9 +40,9 @@ public function share(Request $request): array if (auth()->check()) { auth()->user()->setRelation('person', auth()->user()->person()); } - + $navigation = (new ConditionService)->navigation(); return array_merge(parent::share($request), [ - 'navigation' => $navigation = (new ConditionService)->navigation(), + 'navigation' => $navigation, 'current_navigation' => $navigation->where('current', true)->first(), 'conversations' => auth()->check() ? Thread::query() ->with(['messages', 'messages.fromPerson', 'messages.toPerson']) diff --git a/app/Jobs/Notifications/BuildSummaryNotificationJob.php b/app/Jobs/Notifications/BuildSummaryNotificationJob.php index e68dd936..7d5abee9 100644 --- a/app/Jobs/Notifications/BuildSummaryNotificationJob.php +++ b/app/Jobs/Notifications/BuildSummaryNotificationJob.php @@ -61,6 +61,7 @@ public function handle( $user->notify(new SummaryNotification( $headlines->toArray(), + $weather )); } } diff --git a/app/Jobs/SyncMailboxIfCredentialsAreSet.php b/app/Jobs/SyncMailboxIfCredentialsAreSet.php index 18af23f8..9f99a76b 100644 --- a/app/Jobs/SyncMailboxIfCredentialsAreSet.php +++ b/app/Jobs/SyncMailboxIfCredentialsAreSet.php @@ -6,6 +6,7 @@ use App\Models\Credential; use App\Models\Person; +use App\Models\User; use App\Services\Messaging\ImapFactoryService; use Carbon\Carbon; use Illuminate\Bus\Batchable; @@ -124,6 +125,7 @@ protected function getPersonFromEmail(array $message) $person = Person::create([ 'name' => $fromName, 'emails' => [$fromEmail], + 'user_id' => User::firstWhere('email', env('SPORK_ADMIN_EMAILS'))->id, ]); } $emails = array_values(array_unique(array_filter(array_merge($person->emails, [$message['from']['email']]), fn ($val) => ! empty($val)))); diff --git a/app/Models/ExternalRssFeed.php b/app/Models/ExternalRssFeed.php index eec8b421..3fd4d1d9 100644 --- a/app/Models/ExternalRssFeed.php +++ b/app/Models/ExternalRssFeed.php @@ -4,7 +4,7 @@ namespace App\Models; -use App\Actions\Spork\Domains\ApplyTagToModelAction; +use App\Actions\Spork\ApplyTagToModelAction; use App\Events\Models\ExternalRssFeed\ExternalRssFeedCreated; use App\Events\Models\ExternalRssFeed\ExternalRssFeedCreating; use App\Events\Models\ExternalRssFeed\ExternalRssFeedDeleted; diff --git a/app/Models/Finance/Account.php b/app/Models/Finance/Account.php index 243b3fd2..acd0a052 100644 --- a/app/Models/Finance/Account.php +++ b/app/Models/Finance/Account.php @@ -17,6 +17,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; class Account extends Model implements Crud { @@ -49,4 +50,9 @@ public function credential(): BelongsTo { return $this->belongsTo(Credential::class); } + + public function transactions(): HasMany + { + return $this->hasMany(Transaction::class); + } } diff --git a/app/Models/Finance/Transaction.php b/app/Models/Finance/Transaction.php index 17774a8a..82c41bb6 100644 --- a/app/Models/Finance/Transaction.php +++ b/app/Models/Finance/Transaction.php @@ -11,6 +11,7 @@ use App\Events\Models\Transaction\TransactionDeleting; use App\Events\Models\Transaction\TransactionUpdated; use App\Events\Models\Transaction\TransactionUpdating; +use App\Models\Credential; use App\Models\Crud; use App\Models\Taggable; use App\Models\Traits\ScopeQSearch; @@ -69,8 +70,8 @@ public function account(): BelongsTo return $this->belongsTo(Account::class, 'account_id', 'account_id'); } - public function user(): HasManyThrough + public function credential(): HasManyThrough { - return $this->hasManyThrough(User::class, Account::class); + return $this->hasManyThrough(Credential::class, Account::class, 'credential_id', 'id', 'account_id', 'account_id'); } } diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 275a6db0..b697c9c4 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -33,6 +33,8 @@ class Tag extends \Spatie\Tags\Tag implements Conditionable, Crud, ModelQuery public $fillable = ['name', 'slug', 'must_all_conditions_pass', 'type', 'order_column']; + public $casts = ['name' => 'json']; + public $dispatchesEvents = [ 'created' => TagCreated::class, 'creating' => TagCreating::class, diff --git a/app/Notifications/Daily/SummaryNotification.php b/app/Notifications/Daily/SummaryNotification.php index a9facb67..763b431d 100644 --- a/app/Notifications/Daily/SummaryNotification.php +++ b/app/Notifications/Daily/SummaryNotification.php @@ -19,6 +19,7 @@ public function __construct( // Transactions from a period, // domain expirations public ?array $articles, + public ?Forecast $forecast, ) { // } @@ -35,6 +36,7 @@ public function toMail(object $notifiable): MailMessage 'emails.daily.summary', [ 'articles' => $this->articles, + 'weather' => $this->forecast, ] ); diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index ae03868a..fc48bbed 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,6 +5,7 @@ namespace App\Providers; use App\Contracts\Repositories\CredentialRepositoryContract; +use App\Contracts\Services\Documents\PdfParserServiceContract; use App\Contracts\Services\ImapServiceContract; use App\Contracts\Services\JiraServiceContract; use App\Contracts\Services\NamecheapServiceContract; @@ -27,6 +28,7 @@ use App\Operations\Operator; use App\Repositories\CredentialRepository; use App\Services\Code; +use App\Services\Documents\PdfParserService; use App\Services\Finance\PlaidService; use App\Services\JiraService; use App\Services\Messaging\ImapCredentialService; @@ -83,6 +85,7 @@ public function register(): void $this->app->bind(WeatherServiceContract::class, OpenWeatherService::class); $this->app->bind(JiraServiceContract::class, JiraService::class); $this->app->alias(Operator::class, 'operator'); + $this->app->bind(PdfParserServiceContract::class, PdfParserService::class); } /** diff --git a/app/Services/ConditionService.php b/app/Services/ConditionService.php index 89b62b5f..99e962a7 100644 --- a/app/Services/ConditionService.php +++ b/app/Services/ConditionService.php @@ -52,6 +52,8 @@ class ConditionService public function navigation() { + $parsedUrl = parse_url(request()->getRequestUri()); + // So we want to filter out any nav items $navItems = Navigation::query() ->with('conditions', 'children') @@ -59,12 +61,18 @@ public function navigation() ->whereNull('parent_id') ->orderBy('order') ->get() - ->map(function (Navigation $item) { - $item->current = $item->href === request()->getRequestUri() || ($item->children->isNotEmpty() && $item->children->filter(fn ($item) => $item->href === request()->getRequestUri())->count() > 0); - + ->map(function (Navigation $item) use ($parsedUrl) { + $item->current = $item->href === request()->getRequestUri() || ( + $item->children->isNotEmpty() && + // We don't want to use the query param in the comparison + $item->children->filter(fn ($item) => $item->href === $parsedUrl['path']) + ->count() > 0 + ); return $item; }); + ; + return $navItems->filter(fn (Navigation $item) => $this->process($item)); } diff --git a/app/Services/Development/DescribeTableService.php b/app/Services/Development/DescribeTableService.php index 93633c5d..c8e7589e 100644 --- a/app/Services/Development/DescribeTableService.php +++ b/app/Services/Development/DescribeTableService.php @@ -103,7 +103,7 @@ public function describe(Model $model): array foreach ($notedInstances as $class) { $instance = app($class); if (in_array($model::class, $instance->models)) { - $arrayedInstance = (array) $instance; + $arrayedInstance = (array)$instance; if (method_exists($instance, 'fields')) { $arrayedInstance['fields'] = $instance->fields(); @@ -156,7 +156,15 @@ public function describe(Model $model): array 'required' => $mapField(array_filter($description, fn ($query) => $query->Null === 'NO' && $query->Extra !== 'auto_increment')), ], $model instanceof Taggable ? [ 'tags' => Tag::query()->whereNull('type')->orWhere('type', Str::singular($model->getTable()))->get(), - ] : []); + ] : [], + [ + 'permissions' => [ + 'create' => auth()->user()->can('create_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'), + 'update' => auth()->user()->can('update_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'), + 'delete' => auth()->user()->can('delete_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'), + 'delete_any' => auth()->user()->can('delete_any_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'), + ] + ]); } public function describeTable(string $table): array diff --git a/app/Services/Documents/MenuCardParser.php b/app/Services/Documents/MenuCardParser.php new file mode 100644 index 00000000..b68f45ff --- /dev/null +++ b/app/Services/Documents/MenuCardParser.php @@ -0,0 +1,178 @@ +parserService = $parserService; + } + + public function getAllIdentifiers(string $filename): array + { + $pdfContents = $this->parseAndHandleEncryptedPdf($filename); + + dd($pdfContents); + $replacements = [ + " " => " ", + "\n" => " ", + "\t" => " ", + " - " => "-", + "- " => "-", + " -" => "-", + ]; + + foreach ($replacements as $search => $replace) { + $pdfContents = str_replace($search, $replace, $pdfContents); + } + + $lines = array_values(array_filter(explode("\n", $pdfContents))); + $matches = collect([]); + + foreach ($lines as $line) { + if (preg_match_all('/(1[\s]?A[\s]?4[\s]?.+?[^A-Z\d])|([A-Z-]{1,3}-[A-Z-0-9]{1,3}.+?[^A-Z\d])/m', $line, $allMatches)) { + $matches = collect($allMatches) + ->flatten() + ->map(fn ($str) => preg_replace('/[^[:print:]]/', '', trim(str_replace(' ', '', $str), " \t\n\r\0\x0B:)("))) + ->filter() + // The MRA email gets caught in this regex, so let's filter out anything starting with MRA + ->filter(fn ($str) => !str_starts_with($str, 'MRA') && !str_starts_with($str, 'AGE') && !str_starts_with($str, 'LLC')) + ->merge($matches) + ->unique(); + } + } + + return $matches->toArray(); + } + + public function getRecallsFromPdfFile(string $filename): array + { + $pdfContents = $this->parseAndHandleEncryptedPdf($filename); + $lines = array_values(array_filter(explode("\n", $pdfContents))); + return $this->parsePdf($lines); + } + + public function getPackageIdsFromPdfFile(string $filename): array + { + $pdfContents = $this->parseAndHandleEncryptedPdf($filename); + $lines = array_values(array_filter(explode("\n", $pdfContents))); + return $this->parsePackagesFromPdf($lines); + } + + protected function parseAndHandleEncryptedPdf(string $filename, int $recursionCounter = 0): string + { + try { + $pdfText = $this->parserService->getPdfTextFromFile($filename); + + if (empty($pdfText)) { + throw new \Exception('Secured pdf file are currently not supported.'); + } + return $pdfText; + } catch (\Exception $e) { + if ($e->getMessage() === 'Secured pdf file are currently not supported.' && $recursionCounter < 3) { + // We can actually use pdftk to decrypt the file and then re-run the extraction. + $pdf = new Pdf(); + $pdf->addFile($filename, null, '')->saveAs($filename); + return $this->parserService->getPdfTextFromFile($filename); + } + throw $e; + } + } + + protected function parsePackagesFromPdf(array $lines): array + { + $packages = []; + foreach ($lines as $line) { + if ($package = $this->isPackageBlock($line)) { + $packages[] = $package; + } + } + + return $packages; + } + + protected function parsePdf(array $lines): array + { + $recalls = []; + + $currentStore = null; + $currentPackage = null; + + foreach ($lines as $line) { + $isStoreBlock = $this->isStoreBlock($line); + $isPackageBlock = $this->isPackageBlock($line); + + if (!empty($isStoreBlock)) { + // New store has been discovered, set package info and reset + $currentStore = $isStoreBlock; + $currentPackage = null; + continue; + } + + if (!empty($isPackageBlock)) { + // New package discovered + $currentPackage = $isPackageBlock; + continue; + } + + if (empty($currentPackage)) continue; + + if (empty($recalls[$currentStore])) { + $recalls[$currentStore] = []; + } + + if (empty($recalls[$currentStore][$currentPackage])) { + $recalls[$currentStore][$currentPackage] = ''; + } + + $recalls[$currentStore][$currentPackage] .= ' ' . str_replace(array_keys($recalls), '', $this->trim($line)); + } + + /** + * Depending on how a package recall block is structured there may be another store name trailing at the end + * of the recall info. Here we will just filter out store names from the recall info based on the store names + * that are in our recalls array. + */ + $stores = array_keys($recalls); + foreach ($recalls as $store => $packages) { + foreach ($packages as $package => $recallInfo) { + $recalls[$store][$package] = $this->trim(str_replace($stores, '', $recallInfo)); + } + } + return $recalls; + } + + protected function isStoreBlock(string $line): ?string + { + $storeNameRegex = '/This recall affects.*from ([a-zA-Z0-9\-_ &]*).*/i'; + preg_match_all($storeNameRegex, $line, $matches); + if (!empty($matches[1])) { + return $this->trim($matches[1][0]); + } + + return null; + } + + protected function isPackageBlock(string $line): ?string + { + $packageRegex = '/[Package]? ?#? ?(1A[A-Z0-9]*)/i'; + preg_match_all($packageRegex, $line, $matches); + if (!empty($matches[1])) { + return $this->trim($matches[1][0]); + } + + return null; + } + + protected function trim(string $value): string + { + return trim($value, "\t\r\n "); + } +} diff --git a/app/Services/Documents/PdfParserService.php b/app/Services/Documents/PdfParserService.php new file mode 100644 index 00000000..dddefe91 --- /dev/null +++ b/app/Services/Documents/PdfParserService.php @@ -0,0 +1,68 @@ +parser->parseFile($filename); + + $menuData = []; + + foreach ($pdf->getPages() as $page) { + $dataChunks = $page->getDataTm(); + + foreach ($dataChunks as $index => $chunk) { + if ($index < 18 ) { + continue; + } + if (!isset($item)) { + $item = []; + } + + $text = trim(match(count($chunk)) { + 2 => $chunk[1], + }); + + if (empty($text)) { + continue; + } + + $item[] = $text; + + preg_match('/\d{1,4}\.\d{2}/', $text, $matches); + + if (empty($matches)) { + continue; + } + + $menuData[$item[0]] = $item; + unset($item); + } + } + + return json_encode($menuData); + } + + public function getPdfTextFromRawContent(string $contents): string + { + $pdf = $this->parser->parseContent($contents); + return $this->readPdfText($pdf); + } + + protected function readPdfText(Document $pdf): string + { + return $pdf->getText(); + } +} diff --git a/app/Services/Documents/PdfReaderService.php b/app/Services/Documents/PdfReaderService.php new file mode 100644 index 00000000..d65736cf --- /dev/null +++ b/app/Services/Documents/PdfReaderService.php @@ -0,0 +1,43 @@ +rawDataParser->parseData($content); + if (isset($xref['trailer']['encrypt'])) { + $this->stripEncryption($xref); + } + + if (empty($data)) { + throw new \Exception('Object list not found. Possible secured file.'); + } + + // Create destination object. + $document = new Document(); + $this->objects = []; + + foreach ($data as $id => $structure) { + $this->parseObject($id, $structure, $document); + unset($data[$id]); + } + + $document->setTrailer($this->parseTrailer($xref['trailer'], $document)); + $document->setObjects($this->objects); + + return $document; + } + + protected function stripEncryption(array &$xref): void + { + if (is_string($xref['trailer']['size'])) { + $xref['trailer']['encrypt'] = null; + } + } +} diff --git a/composer.json b/composer.json index ac713f6a..5b773bee 100644 --- a/composer.json +++ b/composer.json @@ -32,11 +32,13 @@ "league/flysystem-ftp": "^3.0", "lesstif/php-jira-rest-client": "^5.7", "meilisearch/meilisearch-php": "^1.6", + "mikehaertl/php-pdftk": "^0.13.1", "mustache/mustache": "^2.14", "nativephp/electron": "^0.5.0", "nette/php-generator": "*", "php-imap/php-imap": "^5.0", "pusher/pusher-php-server": "^7.0", + "smalot/pdfparser": "^2.10", "spatie/laravel-activitylog": "^4.8", "spatie/laravel-feed": "^4.4", "spatie/laravel-ignition": "^2.4", diff --git a/composer.lock b/composer.lock index 2b73ef2b..d32c1579 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "41377b7b0be5ee3d276aa3f1fe5b3577", + "content-hash": "81f5969e34e14bf81318c209517cdcf9", "packages": [ { "name": "bacon/bacon-qr-code", @@ -2198,22 +2198,23 @@ }, { "name": "inertiajs/inertia-laravel", - "version": "v1.1.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/inertiajs/inertia-laravel.git", - "reference": "576fba4da6f2ba6348ddf57a750c73231904d598" + "reference": "5675663d9619528544cc2dca60e0f8b9603980ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/576fba4da6f2ba6348ddf57a750c73231904d598", - "reference": "576fba4da6f2ba6348ddf57a750c73231904d598", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/5675663d9619528544cc2dca60e0f8b9603980ae", + "reference": "5675663d9619528544cc2dca60e0f8b9603980ae", "shasum": "" }, "require": { "ext-json": "*", "laravel/framework": "^8.74|^9.0|^10.0|^11.0", - "php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0" + "php": "^7.3|~8.0.0|~8.1.0|~8.2.0|~8.3.0", + "symfony/console": "^5.3|^6.0|^7.0" }, "require-dev": { "mockery/mockery": "^1.3.3", @@ -2261,7 +2262,7 @@ ], "support": { "issues": "https://github.com/inertiajs/inertia-laravel/issues", - "source": "https://github.com/inertiajs/inertia-laravel/tree/v1.1.0" + "source": "https://github.com/inertiajs/inertia-laravel/tree/v1.2.0" }, "funding": [ { @@ -2269,7 +2270,7 @@ "type": "github" } ], - "time": "2024-05-16T01:41:06+00:00" + "time": "2024-05-17T22:12:22+00:00" }, { "name": "justinrainbow/json-schema", @@ -2466,16 +2467,16 @@ }, { "name": "laravel/fortify", - "version": "v1.21.2", + "version": "v1.21.3", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "cb122ceec7f8d0231985c1dde8161b3c561bfe90" + "reference": "a725684d17959c4750f3b441ff2e94ecde7793a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/cb122ceec7f8d0231985c1dde8161b3c561bfe90", - "reference": "cb122ceec7f8d0231985c1dde8161b3c561bfe90", + "url": "https://api.github.com/repos/laravel/fortify/zipball/a725684d17959c4750f3b441ff2e94ecde7793a1", + "reference": "a725684d17959c4750f3b441ff2e94ecde7793a1", "shasum": "" }, "require": { @@ -2527,20 +2528,20 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2024-04-25T14:17:43+00:00" + "time": "2024-05-08T18:07:38+00:00" }, { "name": "laravel/framework", - "version": "v11.7.0", + "version": "v11.8.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "e5ac72f513f635f208024aa76b8a04efc1b47f93" + "reference": "ceb892a25817c888ef3df4d1a2af9cac53978300" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/e5ac72f513f635f208024aa76b8a04efc1b47f93", - "reference": "e5ac72f513f635f208024aa76b8a04efc1b47f93", + "url": "https://api.github.com/repos/laravel/framework/zipball/ceb892a25817c888ef3df4d1a2af9cac53978300", + "reference": "ceb892a25817c888ef3df4d1a2af9cac53978300", "shasum": "" }, "require": { @@ -2665,7 +2666,7 @@ "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", "ext-pdo": "Required to use all database features.", "ext-posix": "Required to use all features of the queue worker.", - "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "laravel/tinker": "Required to use the tinker console command (^2.0).", @@ -2732,7 +2733,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-05-07T13:41:51+00:00" + "time": "2024-05-21T17:57:45+00:00" }, { "name": "laravel/horizon", @@ -2815,16 +2816,16 @@ }, { "name": "laravel/jetstream", - "version": "v5.1.0", + "version": "v5.1.1", "source": { "type": "git", "url": "https://github.com/laravel/jetstream.git", - "reference": "8bffd5336bfac4d6f0098b50ee7c3e3559714ddc" + "reference": "30bde139ca1c41d10a58c67f8daa2e8cd3a0be93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/jetstream/zipball/8bffd5336bfac4d6f0098b50ee7c3e3559714ddc", - "reference": "8bffd5336bfac4d6f0098b50ee7c3e3559714ddc", + "url": "https://api.github.com/repos/laravel/jetstream/zipball/30bde139ca1c41d10a58c67f8daa2e8cd3a0be93", + "reference": "30bde139ca1c41d10a58c67f8daa2e8cd3a0be93", "shasum": "" }, "require": { @@ -2878,20 +2879,20 @@ "issues": "https://github.com/laravel/jetstream/issues", "source": "https://github.com/laravel/jetstream" }, - "time": "2024-05-06T17:10:37+00:00" + "time": "2024-05-13T17:01:27+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.21", + "version": "v0.1.22", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "23ea808e8a145653e0ab29e30d4385e49f40a920" + "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/23ea808e8a145653e0ab29e30d4385e49f40a920", - "reference": "23ea808e8a145653e0ab29e30d4385e49f40a920", + "url": "https://api.github.com/repos/laravel/prompts/zipball/37f94de71758dbfbccc9d299b0e5eb76e02a40f5", + "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5", "shasum": "" }, "require": { @@ -2934,22 +2935,22 @@ "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.21" + "source": "https://github.com/laravel/prompts/tree/v0.1.22" }, - "time": "2024-04-30T12:46:16+00:00" + "time": "2024-05-10T19:22:18+00:00" }, { "name": "laravel/reverb", - "version": "v1.0.0-beta10", + "version": "v1.0.0-beta11", "source": { "type": "git", "url": "https://github.com/laravel/reverb.git", - "reference": "78056b18086a5dcd0c50db8398e9be313e22624b" + "reference": "f0cee423dce0ed8c8d65dbfdfc531b188627a50d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/reverb/zipball/78056b18086a5dcd0c50db8398e9be313e22624b", - "reference": "78056b18086a5dcd0c50db8398e9be313e22624b", + "url": "https://api.github.com/repos/laravel/reverb/zipball/f0cee423dce0ed8c8d65dbfdfc531b188627a50d", + "reference": "f0cee423dce0ed8c8d65dbfdfc531b188627a50d", "shasum": "" }, "require": { @@ -3016,9 +3017,9 @@ ], "support": { "issues": "https://github.com/laravel/reverb/issues", - "source": "https://github.com/laravel/reverb/tree/v1.0.0-beta10" + "source": "https://github.com/laravel/reverb/tree/v1.0.0-beta11" }, - "time": "2024-05-02T14:46:35+00:00" + "time": "2024-05-09T17:23:01+00:00" }, { "name": "laravel/sanctum", @@ -3876,6 +3877,145 @@ }, "time": "2024-05-06T13:58:08+00:00" }, + { + "name": "mikehaertl/php-pdftk", + "version": "0.13.1", + "source": { + "type": "git", + "url": "https://github.com/mikehaertl/php-pdftk.git", + "reference": "3851b08c1027489e48387d7c14c27bc295d98239" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikehaertl/php-pdftk/zipball/3851b08c1027489e48387d7c14c27bc295d98239", + "reference": "3851b08c1027489e48387d7c14c27bc295d98239", + "shasum": "" + }, + "require": { + "mikehaertl/php-shellcommand": "^1.6.3", + "mikehaertl/php-tmpfile": "^1.1.0", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">4.0 <9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "mikehaertl\\pdftk\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Haertl", + "email": "haertl.mike@gmail.com" + } + ], + "description": "A PDF conversion and form utility based on pdftk.", + "keywords": [ + "pdf", + "pdftk" + ], + "support": { + "issues": "https://github.com/mikehaertl/php-pdftk/issues", + "source": "https://github.com/mikehaertl/php-pdftk/tree/0.13.1" + }, + "time": "2023-11-03T16:06:08+00:00" + }, + { + "name": "mikehaertl/php-shellcommand", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/mikehaertl/php-shellcommand.git", + "reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/e79ea528be155ffdec6f3bf1a4a46307bb49e545", + "reference": "e79ea528be155ffdec6f3bf1a4a46307bb49e545", + "shasum": "" + }, + "require": { + "php": ">= 5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">4.0 <=9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "mikehaertl\\shellcommand\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Härtl", + "email": "haertl.mike@gmail.com" + } + ], + "description": "An object oriented interface to shell commands", + "keywords": [ + "shell" + ], + "support": { + "issues": "https://github.com/mikehaertl/php-shellcommand/issues", + "source": "https://github.com/mikehaertl/php-shellcommand/tree/1.7.0" + }, + "time": "2023-04-19T08:25:22+00:00" + }, + { + "name": "mikehaertl/php-tmpfile", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/mikehaertl/php-tmpfile.git", + "reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mikehaertl/php-tmpfile/zipball/70a5b70b17bc0d9666388e6a551ecc93d0b40a10", + "reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10", + "shasum": "" + }, + "require-dev": { + "php": ">=5.3.0", + "phpunit/phpunit": ">4.0 <=9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "mikehaertl\\tmp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Härtl", + "email": "haertl.mike@gmail.com" + } + ], + "description": "A convenience class for temporary files", + "keywords": [ + "files" + ], + "support": { + "issues": "https://github.com/mikehaertl/php-tmpfile/issues", + "source": "https://github.com/mikehaertl/php-tmpfile/tree/1.2.1" + }, + "time": "2021-03-01T18:26:25+00:00" + }, { "name": "mobiledetect/mobiledetectlib", "version": "4.8.06", @@ -7077,6 +7217,57 @@ }, "time": "2023-09-03T09:24:00+00:00" }, + { + "name": "smalot/pdfparser", + "version": "v2.10.0", + "source": { + "type": "git", + "url": "https://github.com/smalot/pdfparser.git", + "reference": "14adf318f8620a6195c0b00d51c6a507837b9ff4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smalot/pdfparser/zipball/14adf318f8620a6195c0b00d51c6a507837b9ff4", + "reference": "14adf318f8620a6195c0b00d51c6a507837b9ff4", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-zlib": "*", + "php": ">=7.1", + "symfony/polyfill-mbstring": "^1.18" + }, + "type": "library", + "autoload": { + "psr-0": { + "Smalot\\PdfParser\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Sebastien MALOT", + "email": "sebastien@malot.fr" + } + ], + "description": "Pdf parser library. Can read and extract information from pdf file.", + "homepage": "https://www.pdfparser.org", + "keywords": [ + "extract", + "parse", + "parser", + "pdf", + "text" + ], + "support": { + "issues": "https://github.com/smalot/pdfparser/issues", + "source": "https://github.com/smalot/pdfparser/tree/v2.10.0" + }, + "time": "2024-04-29T06:36:50+00:00" + }, { "name": "spatie/backtrace", "version": "1.6.1", @@ -11322,16 +11513,16 @@ }, { "name": "laravel/pint", - "version": "v1.15.3", + "version": "v1.16.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "3600b5d17aff52f6100ea4921849deacbbeb8656" + "reference": "1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/3600b5d17aff52f6100ea4921849deacbbeb8656", - "reference": "3600b5d17aff52f6100ea4921849deacbbeb8656", + "url": "https://api.github.com/repos/laravel/pint/zipball/1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98", + "reference": "1b3a3dc5bc6a81ff52828ba7277621f1d49d6d98", "shasum": "" }, "require": { @@ -11342,11 +11533,11 @@ "php": "^8.1.0" }, "require-dev": { - "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", + "friendsofphp/php-cs-fixer": "^3.57.1", + "illuminate/view": "^10.48.10", + "larastan/larastan": "^2.9.6", + "laravel-zero/framework": "^10.4.0", + "mockery/mockery": "^1.6.12", "nunomaduro/termwind": "^1.15.1", "pestphp/pest": "^2.34.7" }, @@ -11384,20 +11575,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-04-30T15:02:26+00:00" + "time": "2024-05-21T18:08:25+00:00" }, { "name": "laravel/sail", - "version": "v1.29.1", + "version": "v1.29.2", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "8be4a31150eab3b46af11a2e7b2c4632eefaad7e" + "reference": "a8e4e749735ba2f091856eafeb3f99db8cd6b621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/8be4a31150eab3b46af11a2e7b2c4632eefaad7e", - "reference": "8be4a31150eab3b46af11a2e7b2c4632eefaad7e", + "url": "https://api.github.com/repos/laravel/sail/zipball/a8e4e749735ba2f091856eafeb3f99db8cd6b621", + "reference": "a8e4e749735ba2f091856eafeb3f99db8cd6b621", "shasum": "" }, "require": { @@ -11447,7 +11638,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2024-03-20T20:09:31+00:00" + "time": "2024-05-16T21:39:11+00:00" }, { "name": "mockery/mockery", diff --git a/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php b/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php new file mode 100644 index 00000000..2af2670b --- /dev/null +++ b/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php @@ -0,0 +1,28 @@ +integer('priority')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('dns_records', function (Blueprint $table) { + $table->dropColumn('priority'); + }); + } +}; diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile index 968b5cc0..f2adff32 100644 --- a/docker/base/Dockerfile +++ b/docker/base/Dockerfile @@ -18,7 +18,7 @@ RUN apt-get update \ && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x14aa40ec0831756756d7f66c4f4ea0aae5267a6c' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \ && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ && apt-get update \ - && apt-get install -y php8.2-cli php8.2-dev \ + && apt-get install -y pdftk php8.2-cli php8.2-dev \ php8.2-pgsql php8.2-sqlite3 php8.2-gd php8.2-imagick \ php8.2-curl \ php8.2-imap php8.2-mysql php8.2-mbstring \ diff --git a/resources/js/Components/Modal.vue b/resources/js/Components/Modal.vue index 93b74f30..d143bf20 100644 --- a/resources/js/Components/Modal.vue +++ b/resources/js/Components/Modal.vue @@ -68,20 +68,24 @@ const maxWidthClass = computed(() => { leave-from-class="opacity-100" leave-to-class="opacity-0" > -
Successfully saved!
+Anyone with a link can now view this file.
+Discussion moved
+Lorem ipsum dolor sit amet consectetur adipisicing elit oluptatum tenetur.
++ | {{header}} |
---|---|
+ |
|
+ |
-
+
-
-
+
@@ -150,10 +171,14 @@ const log = console.log;
-
@@ -163,15 +188,17 @@ const log = console.log;
-
+
-
+
diff --git a/resources/js/Components/Spork/Atoms/Collapsible.vue b/resources/js/Components/Spork/Atoms/Collapsible.vue
new file mode 100644
index 00000000..b42c35db
--- /dev/null
+++ b/resources/js/Components/Spork/Atoms/Collapsible.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
diff --git a/resources/js/Pages/Notifications.vue b/resources/js/Pages/Notifications.vue
new file mode 100644
index 00000000..fb435223
--- /dev/null
+++ b/resources/js/Pages/Notifications.vue
@@ -0,0 +1,67 @@
+
+ + Notifications ++ +
+
+
+
+
+
+
+
+
+
+
+
+ Summary
+ {{notification.data?.weather?.temperature}}*F
+ {{notification.data?.weather?.condition_image}}
+
+ notification.data?.weather
+
+
+
+
+
+
+ {{formatDate(notification.created_at)}}
+
+
+
+
+
-
@@ -225,19 +225,16 @@ const reply_all = async () => {
loading.value = true;
closeContextMenu();
await triggerMailLoading();
-
}
const forward = async () => {
loading.value = true;
closeContextMenu();
await triggerMailLoading();
-
}
const apply_tag = async () => {
loading.value = true;
closeContextMenu();
await triggerMailLoading();
-
}
const delete_mail = async () => {
loading.value = true;
diff --git a/resources/js/Pages/Postal/Index.vue b/resources/js/Pages/Postal/Index.vue
index 0a2ac37e..167af174 100644
--- a/resources/js/Pages/Postal/Index.vue
+++ b/resources/js/Pages/Postal/Index.vue
@@ -17,7 +17,7 @@
-
+
Open a thread...
diff --git a/resources/js/app.js b/resources/js/app.js
index 8eebe59d..97357a96 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -12,6 +12,16 @@ import BuilderText from './Builder/Components/BuilderText.vue';
import Notifications from 'notiwind';
import Grid from './Components/Grid.vue';
import TitleAndFooterTextCard from "./Builder/Components/Cards/TitleAndFooterTextCard.vue";
+import dayjs from "dayjs";
+import relativeTime from "dayjs/plugin/relativeTime";
+import 'dayjs/locale/en';
+import utc from 'dayjs/plugin/utc';
+
+dayjs.extend(relativeTime);
+dayjs.extend(utc);
+dayjs.locale('en');
+
+window.dayjs = dayjs;
const registeredComponents = [];
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
diff --git a/routes/crud.php b/routes/crud.php
index bbeae1af..060f6a50 100644
--- a/routes/crud.php
+++ b/routes/crud.php
@@ -24,6 +24,7 @@ function developerRoute($name, $model)
Route::post($name.'/{'.$name.'}/restore', [\App\Http\Controllers\Spork\LocalAdminController::class, 'restore'])->name($name.'.restore');
// Soft-deleting
Route::delete($name.'/{'.$name.'}', [\App\Http\Controllers\Spork\LocalAdminController::class, 'destroy'])->name($name.'.destroy');
+ Route::delete($name.'/{'.$name.'}/many', [\App\Http\Controllers\Spork\LocalAdminController::class, 'destroyMany'])->name($name.'.destroyMany');
// Force delete
Route::delete($name.'/{'.$name.'}/force', [\App\Http\Controllers\Spork\LocalAdminController::class, 'forceDestroy'])->name($name.'.forceDestroy');
Route::post($name.'/{'.$name.'}/tags', [\App\Http\Controllers\Spork\LocalAdminController::class, 'tag'])->name($name.'.tags');
diff --git a/routes/pages/spork.php b/routes/pages/spork.php
index 62dd478a..3ad8fcc2 100644
--- a/routes/pages/spork.php
+++ b/routes/pages/spork.php
@@ -85,6 +85,9 @@
Route::prefix('-')->middleware('auth:sanctum', config('jetstream.auth_session'), 'verified')->group(function () {
Route::get('/dashboard', Controllers\Spork\DashboardController::class)->name('dashboard');
+ Route::get('/notifications', function () {
+ return \Inertia\Inertia::render('Notifications');
+ });
Route::get('/projects', [Controllers\Spork\ProjectsController::class, 'index'])->name('projects.index');
Route::get('/projects/{project}', [Controllers\Spork\ProjectsController::class, 'show'])->name('projects.show');
Route::get('/banking', Controllers\Spork\BankingController::class)->name('banking.index');
diff --git a/routes/web.php b/routes/web.php
index 1c0cf8df..1fcbc0e9 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -25,3 +25,4 @@
Route::domain(env('LINK_SHORTENING_DOMAIN', ''))
->group(base_path('routes/pages/link-shortening.php'));
+
From 9d679c2e048aa40a06c2e3d606d27ca7bc202aa7 Mon Sep 17 00:00:00 2001
From: Austin Kregel <5355937+austinkregel@users.noreply.github.com>
Date: Fri, 31 May 2024 21:42:10 -0400
Subject: [PATCH 02/36] Cs fixes from pint
---
.../Documents/PdfParserServiceContract.php | 1 +
.../Spork/LocalAdminController.php | 1 +
app/Http/Middleware/HandleInertiaRequests.php | 1 +
app/Models/Finance/Transaction.php | 1 -
app/Services/ConditionService.php | 3 +-
.../Development/DescribeTableService.php | 18 +++++-----
app/Services/Documents/MenuCardParser.php | 36 ++++++++++++-------
app/Services/Documents/PdfParserService.php | 9 ++---
app/Services/Documents/PdfReaderService.php | 3 +-
...0807_add_priority_to_dns_records_table.php | 2 ++
routes/web.php | 1 -
11 files changed, 45 insertions(+), 31 deletions(-)
diff --git a/app/Contracts/Services/Documents/PdfParserServiceContract.php b/app/Contracts/Services/Documents/PdfParserServiceContract.php
index a4882d03..85965345 100644
--- a/app/Contracts/Services/Documents/PdfParserServiceContract.php
+++ b/app/Contracts/Services/Documents/PdfParserServiceContract.php
@@ -1,4 +1,5 @@
getModel($request);
diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php
index 1ba50905..6aa8cefa 100644
--- a/app/Http/Middleware/HandleInertiaRequests.php
+++ b/app/Http/Middleware/HandleInertiaRequests.php
@@ -41,6 +41,7 @@ public function share(Request $request): array
auth()->user()->setRelation('person', auth()->user()->person());
}
$navigation = (new ConditionService)->navigation();
+
return array_merge(parent::share($request), [
'navigation' => $navigation,
'current_navigation' => $navigation->where('current', true)->first(),
diff --git a/app/Models/Finance/Transaction.php b/app/Models/Finance/Transaction.php
index 82c41bb6..632736bf 100644
--- a/app/Models/Finance/Transaction.php
+++ b/app/Models/Finance/Transaction.php
@@ -16,7 +16,6 @@
use App\Models\Taggable;
use App\Models\Traits\ScopeQSearch;
use App\Models\Traits\ScopeRelativeSearch;
-use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
diff --git a/app/Services/ConditionService.php b/app/Services/ConditionService.php
index 99e962a7..d4cb731e 100644
--- a/app/Services/ConditionService.php
+++ b/app/Services/ConditionService.php
@@ -68,11 +68,10 @@ public function navigation()
$item->children->filter(fn ($item) => $item->href === $parsedUrl['path'])
->count() > 0
);
+
return $item;
});
- ;
-
return $navItems->filter(fn (Navigation $item) => $this->process($item));
}
diff --git a/app/Services/Development/DescribeTableService.php b/app/Services/Development/DescribeTableService.php
index c8e7589e..f1fd2e52 100644
--- a/app/Services/Development/DescribeTableService.php
+++ b/app/Services/Development/DescribeTableService.php
@@ -103,7 +103,7 @@ public function describe(Model $model): array
foreach ($notedInstances as $class) {
$instance = app($class);
if (in_array($model::class, $instance->models)) {
- $arrayedInstance = (array)$instance;
+ $arrayedInstance = (array) $instance;
if (method_exists($instance, 'fields')) {
$arrayedInstance['fields'] = $instance->fields();
@@ -157,14 +157,14 @@ public function describe(Model $model): array
], $model instanceof Taggable ? [
'tags' => Tag::query()->whereNull('type')->orWhere('type', Str::singular($model->getTable()))->get(),
] : [],
- [
- 'permissions' => [
- 'create' => auth()->user()->can('create_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
- 'update' => auth()->user()->can('update_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
- 'delete' => auth()->user()->can('delete_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
- 'delete_any' => auth()->user()->can('delete_any_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
- ]
- ]);
+ [
+ 'permissions' => [
+ 'create' => auth()->user()->can('create_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
+ 'update' => auth()->user()->can('update_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
+ 'delete' => auth()->user()->can('delete_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
+ 'delete_any' => auth()->user()->can('delete_any_'.Str::singular($model->getTable())) || auth()->user()->hasRole('developer'),
+ ],
+ ]);
}
public function describeTable(string $table): array
diff --git a/app/Services/Documents/MenuCardParser.php b/app/Services/Documents/MenuCardParser.php
index b68f45ff..bc3a195c 100644
--- a/app/Services/Documents/MenuCardParser.php
+++ b/app/Services/Documents/MenuCardParser.php
@@ -1,4 +1,5 @@
" ",
- "\n" => " ",
- "\t" => " ",
- " - " => "-",
- "- " => "-",
- " -" => "-",
+ ' ' => ' ',
+ "\n" => ' ',
+ "\t" => ' ',
+ ' - ' => '-',
+ '- ' => '-',
+ ' -' => '-',
];
foreach ($replacements as $search => $replace) {
@@ -43,7 +44,7 @@ public function getAllIdentifiers(string $filename): array
->map(fn ($str) => preg_replace('/[^[:print:]]/', '', trim(str_replace(' ', '', $str), " \t\n\r\0\x0B:)(")))
->filter()
// The MRA email gets caught in this regex, so let's filter out anything starting with MRA
- ->filter(fn ($str) => !str_starts_with($str, 'MRA') && !str_starts_with($str, 'AGE') && !str_starts_with($str, 'LLC'))
+ ->filter(fn ($str) => ! str_starts_with($str, 'MRA') && ! str_starts_with($str, 'AGE') && ! str_starts_with($str, 'LLC'))
->merge($matches)
->unique();
}
@@ -56,6 +57,7 @@ public function getRecallsFromPdfFile(string $filename): array
{
$pdfContents = $this->parseAndHandleEncryptedPdf($filename);
$lines = array_values(array_filter(explode("\n", $pdfContents)));
+
return $this->parsePdf($lines);
}
@@ -63,6 +65,7 @@ public function getPackageIdsFromPdfFile(string $filename): array
{
$pdfContents = $this->parseAndHandleEncryptedPdf($filename);
$lines = array_values(array_filter(explode("\n", $pdfContents)));
+
return $this->parsePackagesFromPdf($lines);
}
@@ -74,12 +77,14 @@ protected function parseAndHandleEncryptedPdf(string $filename, int $recursionCo
if (empty($pdfText)) {
throw new \Exception('Secured pdf file are currently not supported.');
}
+
return $pdfText;
} catch (\Exception $e) {
if ($e->getMessage() === 'Secured pdf file are currently not supported.' && $recursionCounter < 3) {
// We can actually use pdftk to decrypt the file and then re-run the extraction.
$pdf = new Pdf();
$pdf->addFile($filename, null, '')->saveAs($filename);
+
return $this->parserService->getPdfTextFromFile($filename);
}
throw $e;
@@ -109,20 +114,24 @@ protected function parsePdf(array $lines): array
$isStoreBlock = $this->isStoreBlock($line);
$isPackageBlock = $this->isPackageBlock($line);
- if (!empty($isStoreBlock)) {
+ if (! empty($isStoreBlock)) {
// New store has been discovered, set package info and reset
$currentStore = $isStoreBlock;
$currentPackage = null;
+
continue;
}
- if (!empty($isPackageBlock)) {
+ if (! empty($isPackageBlock)) {
// New package discovered
$currentPackage = $isPackageBlock;
+
continue;
}
- if (empty($currentPackage)) continue;
+ if (empty($currentPackage)) {
+ continue;
+ }
if (empty($recalls[$currentStore])) {
$recalls[$currentStore] = [];
@@ -132,7 +141,7 @@ protected function parsePdf(array $lines): array
$recalls[$currentStore][$currentPackage] = '';
}
- $recalls[$currentStore][$currentPackage] .= ' ' . str_replace(array_keys($recalls), '', $this->trim($line));
+ $recalls[$currentStore][$currentPackage] .= ' '.str_replace(array_keys($recalls), '', $this->trim($line));
}
/**
@@ -146,6 +155,7 @@ protected function parsePdf(array $lines): array
$recalls[$store][$package] = $this->trim(str_replace($stores, '', $recallInfo));
}
}
+
return $recalls;
}
@@ -153,7 +163,7 @@ protected function isStoreBlock(string $line): ?string
{
$storeNameRegex = '/This recall affects.*from ([a-zA-Z0-9\-_ &]*).*/i';
preg_match_all($storeNameRegex, $line, $matches);
- if (!empty($matches[1])) {
+ if (! empty($matches[1])) {
return $this->trim($matches[1][0]);
}
@@ -164,7 +174,7 @@ protected function isPackageBlock(string $line): ?string
{
$packageRegex = '/[Package]? ?#? ?(1A[A-Z0-9]*)/i';
preg_match_all($packageRegex, $line, $matches);
- if (!empty($matches[1])) {
+ if (! empty($matches[1])) {
return $this->trim($matches[1][0]);
}
diff --git a/app/Services/Documents/PdfParserService.php b/app/Services/Documents/PdfParserService.php
index dddefe91..b54b7c19 100644
--- a/app/Services/Documents/PdfParserService.php
+++ b/app/Services/Documents/PdfParserService.php
@@ -1,11 +1,11 @@
getDataTm();
foreach ($dataChunks as $index => $chunk) {
- if ($index < 18 ) {
+ if ($index < 18) {
continue;
}
- if (!isset($item)) {
+ if (! isset($item)) {
$item = [];
}
- $text = trim(match(count($chunk)) {
+ $text = trim(match (count($chunk)) {
2 => $chunk[1],
});
@@ -58,6 +58,7 @@ public function getPdfTextFromFile(string $filename): string
public function getPdfTextFromRawContent(string $contents): string
{
$pdf = $this->parser->parseContent($contents);
+
return $this->readPdfText($pdf);
}
diff --git a/app/Services/Documents/PdfReaderService.php b/app/Services/Documents/PdfReaderService.php
index d65736cf..ef6b3b55 100644
--- a/app/Services/Documents/PdfReaderService.php
+++ b/app/Services/Documents/PdfReaderService.php
@@ -1,4 +1,5 @@
rawDataParser->parseData($content);
+ [$xref, $data] = $this->rawDataParser->parseData($content);
if (isset($xref['trailer']['encrypt'])) {
$this->stripEncryption($xref);
}
diff --git a/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php b/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php
index 2af2670b..df75d8fb 100644
--- a/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php
+++ b/database/migrations/2024_05_24_040807_add_priority_to_dns_records_table.php
@@ -1,5 +1,7 @@
group(base_path('routes/pages/link-shortening.php'));
-
From d70ff4eb50bd141c9bed93f401b182090601d6b5 Mon Sep 17 00:00:00 2001
From: Austin Kregel <5355937+austinkregel@users.noreply.github.com>
Date: Fri, 31 May 2024 21:42:29 -0400
Subject: [PATCH 03/36] Add vue multiselect
---
package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/package.json b/package.json
index c8a2de72..7530609b 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,7 @@
"supertest": "^6.3.3",
"vue-draggable-next": "^2.2.1",
"vue-json-pretty": "^2.2.4",
+ "vue-multiselect": "^3.0.0",
"vue-select": "^4.0.0-beta.6",
"vue3-markdown-it": "^1.0.10",
"vuedraggable": "^4.1.0",
From 522d544c98bbaf99d371a6771664e0c0c5d4587b Mon Sep 17 00:00:00 2001
From: Austin Kregel <5355937+austinkregel@users.noreply.github.com>
Date: Mon, 3 Jun 2024 00:03:46 -0400
Subject: [PATCH 04/36] big wip. Update the ssh service so it works properly
again. Update crud view. add pulse and telescope. Rework the design for
navigation. add several new pages
---
app/Console/Commands/BulkScoutImport.php | 28 +
app/Console/Commands/Initialize.php | 54 +
app/Http/Controllers/AdminController.php | 5 +
.../Controllers/Spork/BatchJobController.php | 83 ++
.../Controllers/Spork/DashboardController.php | 23 +-
.../Spork/DevelopmentController.php | 8 +
.../Spork/FileManagerController.php | 2 +
.../Controllers/Spork/InboxController.php | 4 +-
.../Controllers/Spork/ManageController.php | 8 +
app/Jobs/News/UpdateFeed.php | 8 +-
app/Jobs/Registrar/CloudflareSyncJob.php | 2 +-
app/Jobs/Registrar/NamecheapSyncJob.php | 9 +-
app/Models/Article.php | 5 +-
app/Models/Credential.php | 3 +-
app/Models/Domain.php | 10 +
app/Models/DomainRecord.php | 3 +
app/Models/ExternalRssFeed.php | 1 +
app/Models/Finance/Account.php | 15 +
app/Models/Finance/Transaction.php | 11 +-
app/Models/JobBatch.php | 6 +
app/Models/Message.php | 2 +
app/Models/Navigation.php | 15 +-
app/Models/Person.php | 2 +
app/Models/Project.php | 31 +-
app/Models/Research.php | 3 +
app/Models/Server.php | 1 +
app/Models/ShortCode.php | 8 +-
app/Models/Spork/Script.php | 13 +
app/Models/Thread.php | 2 +
app/Models/Traits/ScopeRelativeSearch.php | 11 +-
app/Models/User.php | 1 +
app/Providers/TelescopeServiceProvider.php | 64 ++
app/Services/News/Feeds/AtomFeed.php | 5 +-
app/Services/News/Feeds/RdfFeed.php | 4 +-
app/Services/SshKeyGeneratorService.php | 45 +-
app/Services/SshService.php | 34 +-
composer.json | 4 +
composer.lock | 980 +++++++++++++-----
config/websockets.php | 143 ---
.../2024_06_02_212434_create_pulse_tables.php | 84 ++
..._213101_create_telescope_entries_table.php | 70 ++
docker/websocket/supervisord.conf | 4 +-
.../Components/ContextMenus/ContextMenu.vue | 9 +-
.../ContextMenus/ContextMenuItem.vue | 7 +-
resources/js/Components/DynamicIcon.vue | 1 +
resources/js/Components/Spork/Atoms/Card.vue | 4 +-
.../js/Components/Spork/Atoms/Collapsible.vue | 29 +
.../js/Components/Spork/Atoms/MetricCard.vue | 6 +-
.../Spork/Atoms/NotificationMessage.vue | 11 +-
resources/js/Components/Spork/CrudView.vue | 16 +-
.../Components/Spork/LaravelVuePagination.vue | 4 +-
.../Spork/Molecules/MetricApiCard.vue | 10 +-
.../Spork/RenderlessLaravelVuePagination.vue | 3 +-
.../js/Components/Spork/SporkDynamicInput.vue | 2 +-
resources/js/Components/Spork/SporkInput.vue | 1 +
resources/js/Components/Spork/SporkTable.vue | 14 +-
resources/js/Components/Task.vue | 28 +-
resources/js/Layouts/AppLayout.vue | 20 +-
resources/js/Pages/Admin/BatchJob/Index.vue | 74 ++
resources/js/Pages/Admin/BatchJob/Show.vue | 69 ++
resources/js/Pages/Dashboard.vue | 3 +-
resources/js/Pages/Development/Index.vue | 14 +
resources/js/Pages/Manage/Index.vue | 40 +-
resources/js/Pages/Notifications.vue | 34 +-
resources/js/Pages/Postal/Inbox.vue | 4 +-
resources/js/Pages/Postal/Index.vue | 4 +-
resources/js/Pages/Postal/Thread.vue | 24 +-
resources/js/Pages/Projects/Project.vue | 22 +-
resources/js/Pages/RssFeeds/Index.vue | 78 ++
resources/js/Pages/Search.vue | 39 +
.../views/vendor/pulse/dashboard.blade.php | 2 +
71 files changed, 1796 insertions(+), 590 deletions(-)
create mode 100644 app/Console/Commands/BulkScoutImport.php
create mode 100644 app/Console/Commands/Initialize.php
create mode 100644 app/Http/Controllers/Spork/BatchJobController.php
create mode 100644 app/Providers/TelescopeServiceProvider.php
delete mode 100644 config/websockets.php
create mode 100644 database/migrations/2024_06_02_212434_create_pulse_tables.php
create mode 100644 database/migrations/2024_06_02_213101_create_telescope_entries_table.php
create mode 100644 resources/js/Components/Spork/Atoms/Collapsible.vue
create mode 100644 resources/js/Pages/Admin/BatchJob/Index.vue
create mode 100644 resources/js/Pages/Admin/BatchJob/Show.vue
create mode 100644 resources/js/Pages/Development/Index.vue
create mode 100644 resources/js/Pages/RssFeeds/Index.vue
create mode 100644 resources/js/Pages/Search.vue
diff --git a/app/Console/Commands/BulkScoutImport.php b/app/Console/Commands/BulkScoutImport.php
new file mode 100644
index 00000000..bcac4f3b
--- /dev/null
+++ b/app/Console/Commands/BulkScoutImport.php
@@ -0,0 +1,28 @@
+getClasses();
+
+ foreach($searchableModels as $model) {
+ Artisan::call('scout:import', [
+ 'model' => $model,
+ ]);
+ }
+ }
+}
diff --git a/app/Console/Commands/Initialize.php b/app/Console/Commands/Initialize.php
new file mode 100644
index 00000000..3c8d2e29
--- /dev/null
+++ b/app/Console/Commands/Initialize.php
@@ -0,0 +1,54 @@
+exists()) {
+ $this->info('SSH key already exists');
+ return;
+ }
+
+ if (! User::exists()) {
+ $this->call('make:user');
+ }
+
+ $randomName = Str::random(16);
+ $passKey = Str::random(16);
+
+ [$privateKey, $publicKey] = SshKeyGeneratorService::generate($passKey);
+
+ $publicKeyFile = storage_path('app/keys/'.$randomName.'.pub');
+ $privateKeyFile = storage_path('app/keys/'.$randomName);
+
+ file_put_contents($publicKeyFile, $publicKey);
+ chmod($publicKeyFile, 0600);
+ file_put_contents($privateKeyFile, $privateKey);
+ chmod($privateKeyFile, 0600);
+
+ Credential::create([
+ 'service' => Credential::TYPE_SSH,
+ 'type' => Credential::TYPE_SSH,
+ 'name' => 'SSH',
+ 'user_id' => User::first()->id,
+ 'settings' => [
+ 'pub_key' => $publicKey,
+ 'pub_key_file' => $publicKeyFile,
+ 'private_key' => $privateKey,
+ 'private_key_file' => $privateKeyFile,
+ 'pass_key' => !empty($passKey) ? encrypt($passKey) : '',
+ ],
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php
index 500a566c..e746c48e 100644
--- a/app/Http/Controllers/AdminController.php
+++ b/app/Http/Controllers/AdminController.php
@@ -80,4 +80,9 @@ public function email()
'mail' => '',
]);
}
+
+ public function index()
+ {
+ return
+ }
}
diff --git a/app/Http/Controllers/Spork/BatchJobController.php b/app/Http/Controllers/Spork/BatchJobController.php
new file mode 100644
index 00000000..370e7d67
--- /dev/null
+++ b/app/Http/Controllers/Spork/BatchJobController.php
@@ -0,0 +1,83 @@
+select('*')
+ ->orderByDesc('created_at')
+ ->paginate();
+
+ $paginator = new LengthAwarePaginator(
+ array_map(function ($batch) {
+ $batch->jobs = \DB::table('failed_jobs')
+ ->select('*')
+ ->whereIn('uuid', json_decode($batch->failed_job_ids, true))
+ ->orderByDesc('failed_at')
+ ->get()
+ ->map(function ($job) {
+ $job->parsed_exception = (new Stacktrace)->parse($job->exception);
+ $job->payload = json_decode($job->payload, true);
+
+ return $job;
+ });
+ $batch->failed_at = $batch->jobs->max('failed_at');
+
+ return $batch;
+ }, $batches->items()),
+ $batches->total(),
+ $batches->perPage(),
+ $batches->currentPage()
+ );
+
+ return Inertia::render('Admin/BatchJob/Index', [
+ 'title' => 'Batch Jobs',
+ 'paginator' => $paginator,
+ ]);
+ }
+
+ public function show(Request $request, $batch)
+ {
+ $batches = \DB::table('job_batches')
+ ->select('*')
+ ->orderByDesc('created_at')
+ ->where('id', $batch)
+ ->paginate();
+
+ $paginator = new LengthAwarePaginator(
+ array_map(function ($batch) {
+ $batch->jobs = \DB::table('failed_jobs')
+ ->select('*')
+ ->whereIn('uuid', json_decode($batch->failed_job_ids, true))
+ ->orderByDesc('failed_at')
+ ->get()
+ ->map(function ($job) {
+ $job->parsed_exception = (new Stacktrace)->parse($job->exception);
+ $job->payload = json_decode($job->payload, true);
+
+ return $job;
+ });
+ $batch->failed_at = $batch->jobs->max('failed_at');
+
+ return $batch;
+ }, $batches->items()),
+ $batches->total(),
+ $batches->perPage(),
+ $batches->currentPage()
+ );
+
+ return Inertia::render('Admin/BatchJob/Show', [
+ 'title' => 'Batch Jobs',
+ 'paginator' => $paginator,
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/Spork/DashboardController.php b/app/Http/Controllers/Spork/DashboardController.php
index 26d76cb0..be75ceca 100644
--- a/app/Http/Controllers/Spork/DashboardController.php
+++ b/app/Http/Controllers/Spork/DashboardController.php
@@ -9,16 +9,27 @@
use App\Models\Person;
use App\Models\User;
use Illuminate\Support\Arr;
+use Illuminate\Support\Collection;
use Inertia\Inertia;
class DashboardController extends Controller
{
public function __invoke()
{
- $person = Person::whereJsonContains('emails', auth()->user()->email)
- // for now, this is fine, my email base does support this idea, but I know if someone/
- // wanted to be malicious they could take advantage of this.
- ->first();
+ $person = auth()->user()->person();
+ $batchJobs = JobBatch::query()
+ ->orderByDesc('created_at')
+ ->paginate(request('job_limit', 10), ['*'], 'job_page', request('job_page', 1));
+
+ $batchJobs->setCollection(
+ Collection::make(array_map(function ($batchJob) {
+ $batchJob->failed_at = \DB::table('failed_jobs')
+ ->selectRaw('max(failed_at)')
+ ->whereIn('id', $batchJob->failed_job_ids)
+ ->value('failed_at');
+ return $batchJob;
+ }, $batchJobs->items()))
+ );
return Inertia::render('Dashboard', [
'accounts' => auth()->user()->accounts()
@@ -55,9 +66,7 @@ public function __invoke()
->where('expires_at', '<=', now()->addWeeks(4))
->orderByDesc('expires_at')
->paginate(request('expiring_limit', 15), ['*'], 'expiring_page', request('expiring_page', 1)),
- 'job_batches' => JobBatch::query()
- ->orderByDesc('created_at')
- ->paginate(request('job_limit', 10), ['*'], 'job_page', request('job_page', 1)),
+ 'job_batches' => $batchJobs,
]);
}
}
diff --git a/app/Http/Controllers/Spork/DevelopmentController.php b/app/Http/Controllers/Spork/DevelopmentController.php
index b0bc5c82..246e8785 100644
--- a/app/Http/Controllers/Spork/DevelopmentController.php
+++ b/app/Http/Controllers/Spork/DevelopmentController.php
@@ -4,6 +4,14 @@
namespace App\Http\Controllers\Spork;
+use Inertia\Inertia;
+
class DevelopmentController
{
+ public function index()
+ {
+ return Inertia::render('Development/Index', [
+// 'instances' => LaravelProgrammingStyle::instancesOf(CustomAction::class),
+ ]);
+ }
}
diff --git a/app/Http/Controllers/Spork/FileManagerController.php b/app/Http/Controllers/Spork/FileManagerController.php
index 0e135c77..5ef3a33f 100644
--- a/app/Http/Controllers/Spork/FileManagerController.php
+++ b/app/Http/Controllers/Spork/FileManagerController.php
@@ -4,6 +4,8 @@
namespace App\Http\Controllers\Spork;
+use Inertia\Inertia;
+
class FileManagerController
{
public function __invoke()
diff --git a/app/Http/Controllers/Spork/InboxController.php b/app/Http/Controllers/Spork/InboxController.php
index d1ec2c47..a703b633 100644
--- a/app/Http/Controllers/Spork/InboxController.php
+++ b/app/Http/Controllers/Spork/InboxController.php
@@ -23,11 +23,11 @@ public function index()
public function show(Message $message)
{
- abort_if($message->type !== 'email', 404);
+ abort_if($message->type !== 'email', 405);
$message->load('credential');
- abort_unless($message->credential->user_id === auth()->id(), 404);
+ abort_unless($message->credential->user_id === auth()->id(), 4035);
$message = (new ImapCredentialService($message->credential))->findMessage($message->event_id, true);
$messageBody = base64_decode($message['body']);
diff --git a/app/Http/Controllers/Spork/ManageController.php b/app/Http/Controllers/Spork/ManageController.php
index f8e251a3..365862eb 100644
--- a/app/Http/Controllers/Spork/ManageController.php
+++ b/app/Http/Controllers/Spork/ManageController.php
@@ -7,6 +7,7 @@
use App\Services\Development\DescribeTableService;
use Illuminate\Support\Str;
use Inertia\Inertia;
+use Spatie\Activitylog\Models\Activity;
class ManageController
{
@@ -17,6 +18,13 @@ public function index()
'description' => [
'fillable' => [],
],
+ 'metrics' => Activity::latest()
+ ->paginate(
+ request('limit', 15),
+ ['*'],
+ 'manage_page',
+ request('manage_page', 1)
+ ),
]);
}
diff --git a/app/Jobs/News/UpdateFeed.php b/app/Jobs/News/UpdateFeed.php
index a383a38a..a3bfc5a5 100644
--- a/app/Jobs/News/UpdateFeed.php
+++ b/app/Jobs/News/UpdateFeed.php
@@ -35,11 +35,17 @@ public function handle(\App\Services\News\RssFeedService $service): void
/** @var AbstractFeed $rssFeed */
$rssFeed = $service->fetchRssFeed($this->feed->url);
+ if (empty($rssFeed)) {
+ return;
+ }
+
/** @var FeedItem $feedItem */
foreach ($rssFeed->getData() as $feedItem) {
// If we already have the item's GUID, we must already have this item so we should stop,
// as any items afterwards are probably already in our system as well.
- if ($this->feed->articles()->where('external_guid', $feedItem->getUuidIfExists())->exists()) {
+ if ($this->feed->articles()
+ ->where('external_guid', $feedItem->getUuidIfExists() ?? $feedItem->getUrl())
+ ->exists()) {
break;
}
diff --git a/app/Jobs/Registrar/CloudflareSyncJob.php b/app/Jobs/Registrar/CloudflareSyncJob.php
index d465bf67..5b630b72 100644
--- a/app/Jobs/Registrar/CloudflareSyncJob.php
+++ b/app/Jobs/Registrar/CloudflareSyncJob.php
@@ -36,7 +36,7 @@ public function sync(): void
foreach ($data as $key => $value) {
if ($localDomain->$key instanceof Carbon || $value instanceof Carbon) {
- if ($value instanceof Carbon && ! $value->equalTo($localDomain->$key)) {
+ if ($value instanceof Carbon && (is_null($localDomain->$key) || ! $value->equalTo($localDomain->$key))) {
$localDomain->$key = $value;
} elseif ($localDomain->$key instanceof Carbon && ! $localDomain->$key->equalTo($value)) {
$localDomain->$key = $value;
diff --git a/app/Jobs/Registrar/NamecheapSyncJob.php b/app/Jobs/Registrar/NamecheapSyncJob.php
index 62bb84a9..b9f578df 100644
--- a/app/Jobs/Registrar/NamecheapSyncJob.php
+++ b/app/Jobs/Registrar/NamecheapSyncJob.php
@@ -17,8 +17,10 @@ public function sync(): void
$domains = $this->service->getDomains(100, $page++);
foreach ($domains as $domain) {
- $localDomain = Domain::where('credential_id', $this->credential->id)
- ->where('domain_id', $domain['id'])
+ $localDomain = Domain::query()
+ ->withoutGlobalScope('active')
+ ->where('credential_id', $this->credential->id)
+ ->where('name', $domain['domain'])
->first();
$data = [
@@ -26,12 +28,13 @@ public function sync(): void
'domain_id' => $domain['id'],
'registered_at' => $domain['created_at'],
'expires_at' => $domain['expires_at'],
- 'verification_key' => 'reforged_'.Str::random(48),
];
if (empty($localDomain)) {
$localDomain = new Domain;
$localDomain->credential_id = $this->credential->id;
+ $localDomain->verification_key = 'reforged_'.Str::random(48);
+
}
foreach ($data as $key => $value) {
diff --git a/app/Models/Article.php b/app/Models/Article.php
index ad7c1508..4b1a6751 100644
--- a/app/Models/Article.php
+++ b/app/Models/Article.php
@@ -17,12 +17,14 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
+use Laravel\Scout\Searchable;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
class Article extends Model implements Crud
{
use HasFactory;
+ use Searchable;
use LogsActivity;
use ScopeQSearch;
use ScopeRelativeSearch;
@@ -65,7 +67,7 @@ public static function fromFeedItem(ExternalRssFeed $feed, FeedItem $item): self
$post = new Article();
// If the item's GUID is a v4 UUID, we may as well use it as our UUID.
$post->uuid = $item->getUuidIfExists();
- $post->external_guid = $item->getExternalId();
+ $post->external_guid = $item->getUuidIfExists() ?? $item->getUrl();
$post->author_id = $feed->id;
$post->author_type = get_class($feed);
$post->headline = $item->getTitle();
@@ -95,6 +97,7 @@ public function getActivitylogOptions(): LogOptions
->logOnly(['headline', 'content', 'attachment', 'url'])
->useLogName('article')
->logFillable()
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
}
diff --git a/app/Models/Credential.php b/app/Models/Credential.php
index 4d81f078..25e8ab1c 100644
--- a/app/Models/Credential.php
+++ b/app/Models/Credential.php
@@ -102,6 +102,7 @@ class Credential extends Model implements Crud, ModelQuery
public $fillable = [
'name',
'type',
+ 'user_id',
'service',
'api_key',
'secret_key',
@@ -160,7 +161,7 @@ public function getPrivateKey(): string
public function getPasskey(): string
{
- return decrypt($this->settings['pass_key'] ?? '');
+ return empty($this->settings['pass_key'] ?? '') ? '': decrypt($this->settings['pass_key'] ?? '');
}
public function getActivitylogOptions(): LogOptions
diff --git a/app/Models/Domain.php b/app/Models/Domain.php
index b9e36980..afdcea24 100644
--- a/app/Models/Domain.php
+++ b/app/Models/Domain.php
@@ -18,6 +18,7 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
+use Laravel\Scout\Searchable;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Tags\HasTags;
@@ -27,6 +28,7 @@ class Domain extends Model implements Crud, ModelQuery, Taggable
use HasFactory;
use HasProjectResource;
use HasTags;
+ use Searchable;
use LogsActivity;
use ScopeQSearch;
use ScopeRelativeSearch;
@@ -41,6 +43,13 @@ class Domain extends Model implements Crud, ModelQuery, Taggable
'updating' => DomainUpdating::class,
'updated' => DomainUpdated::class,
];
+ // add a global scope to prevent the querying of expired domains
+ protected static function booted()
+ {
+ static::addGlobalScope('active', function ($query) {
+ $query->where('expires_at', '>', now());
+ });
+ }
protected function casts(): array
{
@@ -65,6 +74,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['name', 'domain_id', 'registered_at'])
->useLogName('domain')
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
}
diff --git a/app/Models/DomainRecord.php b/app/Models/DomainRecord.php
index 7f33336d..509c27a6 100644
--- a/app/Models/DomainRecord.php
+++ b/app/Models/DomainRecord.php
@@ -16,6 +16,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Laravel\Scout\Searchable;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
@@ -23,6 +24,7 @@ class DomainRecord extends Model implements Crud, ModelQuery
{
use HasFactory;
use LogsActivity;
+ use Searchable;
use ScopeQSearch;
use ScopeRelativeSearch;
@@ -59,6 +61,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logFillable()
->logOnlyDirty()
+ ->dontSubmitEmptyLogs()
->useLogName('domain-record');
}
}
diff --git a/app/Models/ExternalRssFeed.php b/app/Models/ExternalRssFeed.php
index 3fd4d1d9..5d5bad64 100644
--- a/app/Models/ExternalRssFeed.php
+++ b/app/Models/ExternalRssFeed.php
@@ -57,6 +57,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['uuid', 'url', 'name', 'profile_photo_path'])
->useLogName('external-rss-feed')
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
}
diff --git a/app/Models/Finance/Account.php b/app/Models/Finance/Account.php
index acd0a052..b2945d38 100644
--- a/app/Models/Finance/Account.php
+++ b/app/Models/Finance/Account.php
@@ -18,10 +18,15 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
+use Laravel\Scout\Searchable;
+use Spatie\Activitylog\LogOptions;
+use Spatie\Activitylog\Traits\LogsActivity;
class Account extends Model implements Crud
{
use HasFactory;
+ use Searchable;
+ use LogsActivity;
use ScopeQSearch;
use ScopeRelativeSearch;
@@ -55,4 +60,14 @@ public function transactions(): HasMany
{
return $this->hasMany(Transaction::class);
}
+
+
+ public function getActivitylogOptions(): LogOptions
+ {
+ return LogOptions::defaults()
+ ->useLogName('account')
+ ->logFillable()
+ ->dontSubmitEmptyLogs()
+ ->logOnlyDirty();
+ }
}
diff --git a/app/Models/Finance/Transaction.php b/app/Models/Finance/Transaction.php
index 632736bf..0e48fcaa 100644
--- a/app/Models/Finance/Transaction.php
+++ b/app/Models/Finance/Transaction.php
@@ -20,11 +20,13 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
+use Laravel\Scout\Searchable;
use Spatie\Tags\HasTags;
class Transaction extends Model implements Crud, ModelQuery, Taggable
{
use HasFactory;
+ use Searchable;
use HasTags;
use ScopeQSearch;
use ScopeRelativeSearch;
@@ -71,6 +73,13 @@ public function account(): BelongsTo
public function credential(): HasManyThrough
{
- return $this->hasManyThrough(Credential::class, Account::class, 'credential_id', 'id', 'account_id', 'account_id');
+ return $this->hasManyThrough(
+ Credential::class,
+ Account::class,
+ 'credential_id',
+ 'id',
+ 'account_id',
+ 'account_id'
+ );
}
}
diff --git a/app/Models/JobBatch.php b/app/Models/JobBatch.php
index c5f8a91c..5505cce5 100644
--- a/app/Models/JobBatch.php
+++ b/app/Models/JobBatch.php
@@ -11,6 +11,8 @@ class JobBatch extends Model
{
use HasFactory;
+ public $incrementing = false;
+
public $fillable = [
'id',
'name',
@@ -24,6 +26,10 @@ class JobBatch extends Model
'finished_at',
];
+ protected $casts = [
+ 'failed_job_ids' => 'json',
+ ];
+
public $dispatchesEvents = [
'created' => \App\Events\Models\JobBatch\JobBatchCreated::class,
'updated' => \App\Events\Models\JobBatch\JobBatchUpdated::class,
diff --git a/app/Models/Message.php b/app/Models/Message.php
index 4af79730..0917af2e 100644
--- a/app/Models/Message.php
+++ b/app/Models/Message.php
@@ -13,6 +13,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Laravel\Scout\Searchable;
use Spatie\Tags\HasTags;
use Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
@@ -22,6 +23,7 @@
/** @mixin \Eloquent */
class Message extends Model implements Taggable
{
+ use Searchable;
use HasFactory, HasJsonRelationships, HasTags;
public $fillable = [
diff --git a/app/Models/Navigation.php b/app/Models/Navigation.php
index 59be7a6b..eb6c4730 100644
--- a/app/Models/Navigation.php
+++ b/app/Models/Navigation.php
@@ -26,7 +26,20 @@ class Navigation extends Model implements Conditionable, Crud
use ScopeQSearch;
use ScopeRelativeSearch;
- public $guarded = [];
+ public $fillable = [
+ 'domain_id',
+ 'parent_id',
+ 'name',
+ 'icon',
+ 'href',
+ 'order',
+ 'authentication_required',
+ 'settings',
+ 'title',
+ 'description',
+ 'pretty_url',
+ 'ugly_url',
+ ];
public $hidden = ['id', 'created_at', 'updated_at'];
diff --git a/app/Models/Person.php b/app/Models/Person.php
index c3423330..085edfc4 100644
--- a/app/Models/Person.php
+++ b/app/Models/Person.php
@@ -15,10 +15,12 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Laravel\Scout\Searchable;
class Person extends Model implements Crud, ModelQuery
{
use HasFactory;
+ use Searchable;
use ScopeRelativeSearch;
public $guarded = [];
diff --git a/app/Models/Project.php b/app/Models/Project.php
index c013ce2c..aff2140d 100644
--- a/app/Models/Project.php
+++ b/app/Models/Project.php
@@ -112,36 +112,6 @@ public function credentialFor(string $service): ?Credential
{
$credential = $this->credentials()->where('service', $service)->first();
- if (! $credential) {
- if ($service === Credential::TYPE_SSH) {
- $randomName = Str::random(16);
-
- $generatorService = new SshKeyGeneratorService(
- privateKeyFile: $privateKeyFile = storage_path('app/keys/'.$randomName.'.key'),
- publicKeyFile: $publicKeyFile = storage_path('app/keys/'.$randomName.'.pub'),
- passKey: $passKey = ''//''tr::random(16),
- );
-
- $credential = $this->credentials()->create([
- 'service' => Credential::TYPE_SSH,
- 'type' => Credential::TYPE_SSH,
- 'name' => 'Forge',
- 'user_id' => auth()->id(),
- 'settings' => [
- 'pub_key' => $generatorService->getPublicKey(),
- 'pub_key_file' => $publicKeyFile,
- 'private_key' => $generatorService->getPrivateKey(),
- 'private_key_file' => $privateKeyFile,
- 'pass_key' => encrypt($passKey),
- ],
- ]);
-
- return $credential;
- }
-
- throw new \Exception('No credential found for '.$service);
- }
-
return $credential;
}
@@ -155,6 +125,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['name', 'team_id'])
->useLogName('project')
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
}
diff --git a/app/Models/Research.php b/app/Models/Research.php
index dc8e6ba1..30c08f79 100644
--- a/app/Models/Research.php
+++ b/app/Models/Research.php
@@ -15,6 +15,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
+use Laravel\Scout\Searchable;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
@@ -22,6 +23,7 @@ class Research extends Model implements Crud
{
use HasFactory;
use LogsActivity;
+ use Searchable;
use ScopeQSearch;
use ScopeRelativeSearch;
@@ -57,6 +59,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['topic', 'notes', 'sources'])
->useLogName('research')
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
}
diff --git a/app/Models/Server.php b/app/Models/Server.php
index 18c8ce08..26d112df 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -75,6 +75,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['name', 'vcpu', 'memory', 'disk', 'cost_per_hour', 'internal_url', 'last_ping_at', 'booted_at', 'turned_off_at', 'os'])
->useLogName('server')
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
}
diff --git a/app/Models/ShortCode.php b/app/Models/ShortCode.php
index 799affae..6aa5ea16 100644
--- a/app/Models/ShortCode.php
+++ b/app/Models/ShortCode.php
@@ -10,13 +10,19 @@
use App\Events\Models\ShortCode\ShortCodeDeleting;
use App\Events\Models\ShortCode\ShortCodeUpdated;
use App\Events\Models\ShortCode\ShortCodeUpdating;
+use App\Models\Traits\ScopeQSearch;
+use App\Models\Traits\ScopeRelativeSearch;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+//use Laravel\Scout\Searchable;
-class ShortCode extends Model
+class ShortCode extends Model implements Crud
{
+// use Searchable;
use HasFactory;
+ use ScopeRelativeSearch;
+ use ScopeQSearch;
public $fillable = [
'short_code',
diff --git a/app/Models/Spork/Script.php b/app/Models/Spork/Script.php
index f3aa5125..fc992ba7 100644
--- a/app/Models/Spork/Script.php
+++ b/app/Models/Spork/Script.php
@@ -13,6 +13,7 @@
use App\Models\Crud;
use App\Models\Traits\ScopeQSearch;
use App\Models\Traits\ScopeRelativeSearch;
+use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@@ -22,6 +23,13 @@ class Script extends Model implements Crud
use ScopeQSearch;
use ScopeRelativeSearch;
+ protected $fillable = [
+ 'name',
+ 'language',
+ 'script',
+ 'user_id',
+ ];
+
public $dispatchesEvents = [
'created' => ScriptCreated::class,
'creating' => ScriptCreating::class,
@@ -30,4 +38,9 @@ class Script extends Model implements Crud
'updating' => ScriptUpdating::class,
'updated' => ScriptUpdated::class,
];
+
+ public function user()
+ {
+ return $this->belongsTo(User::class);
+ }
}
diff --git a/app/Models/Thread.php b/app/Models/Thread.php
index 56e1022e..d02e94c7 100644
--- a/app/Models/Thread.php
+++ b/app/Models/Thread.php
@@ -17,9 +17,11 @@
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
+use Laravel\Scout\Searchable;
class Thread extends Model implements Crud
{
+ use Searchable;
use HasFactory;
use ScopeQSearch;
use ScopeRelativeSearch;
diff --git a/app/Models/Traits/ScopeRelativeSearch.php b/app/Models/Traits/ScopeRelativeSearch.php
index 6ee57d52..5a5e8998 100644
--- a/app/Models/Traits/ScopeRelativeSearch.php
+++ b/app/Models/Traits/ScopeRelativeSearch.php
@@ -23,6 +23,7 @@ public function scopeRelative(Builder $query, string $string): void
$query->where('user_id', auth()->id());
});
} elseif (method_exists($this, 'credential')) {
+
$query->whereHas('credential', function (Builder $query) {
$query->where('user_id', auth()->id());
});
@@ -39,7 +40,15 @@ public function scopeRelative(Builder $query, string $string): void
} elseif (method_exists($this, 'owner')) {
$query->where('owner_id', auth()->id())
->where('owner_type', User::class);
- } else {
+ } elseif (method_exists($this, 'participants')) {
+ $query->whereHas('participants', function (Builder $query) {
+ $query->where('person_id', auth()->user()->person()->id);
+ });
+ } elseif (method_exists($this, 'projects')) {
+ $query->whereHas('projects.team', function (Builder $query) {
+ $query->where('user_id', auth()->id());
+ });
+ }else {
abort(400, 'No user relation found for model');
}
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 894d5537..c265f97b 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -92,6 +92,7 @@ public function getActivitylogOptions(): LogOptions
return LogOptions::defaults()
->logOnly(['name', 'email'])
->useLogName('user')
+ ->dontSubmitEmptyLogs()
->logOnlyDirty();
}
diff --git a/app/Providers/TelescopeServiceProvider.php b/app/Providers/TelescopeServiceProvider.php
new file mode 100644
index 00000000..847dd759
--- /dev/null
+++ b/app/Providers/TelescopeServiceProvider.php
@@ -0,0 +1,64 @@
+hideSensitiveRequestDetails();
+
+ $isLocal = $this->app->environment('local');
+
+ Telescope::filter(function (IncomingEntry $entry) use ($isLocal) {
+ return $isLocal ||
+ $entry->isReportableException() ||
+ $entry->isFailedRequest() ||
+ $entry->isFailedJob() ||
+ $entry->isScheduledTask() ||
+ $entry->hasMonitoredTag();
+ });
+ }
+
+ /**
+ * Prevent sensitive request details from being logged by Telescope.
+ */
+ protected function hideSensitiveRequestDetails(): void
+ {
+ if ($this->app->environment('local')) {
+ return;
+ }
+
+ Telescope::hideRequestParameters(['_token']);
+
+ Telescope::hideRequestHeaders([
+ 'cookie',
+ 'x-csrf-token',
+ 'x-xsrf-token',
+ ]);
+ }
+
+ /**
+ * Register the Telescope gate.
+ *
+ * This gate determines who can access Telescope in non-local environments.
+ */
+ protected function gate(): void
+ {
+ Gate::define('viewTelescope', function ($user) {
+ return in_array($user->email, [
+ //
+ ]);
+ });
+ }
+}
diff --git a/app/Services/News/Feeds/AtomFeed.php b/app/Services/News/Feeds/AtomFeed.php
index 14768501..cc920c0f 100644
--- a/app/Services/News/Feeds/AtomFeed.php
+++ b/app/Services/News/Feeds/AtomFeed.php
@@ -63,7 +63,7 @@ public function getData(): array
}
$feedItem = new FeedItem();
- $feedItem->id = $post['id'];
+ $feedItem->id = (string) $post['id'];
$feedItem->title = $post['title'] ?? null;
$feedItem->content = $post['content'] ?? null;
$feedItem->published_at = $post['published'] ?? $post['updated'];
@@ -72,6 +72,9 @@ public function getData(): array
$feedItem->url = $post['link'];
} elseif (isset($post['link']['@attributes'])) {
$feedItem->url = $post['link']['@attributes']['href'];
+ } else {
+ info('no link', ['context' => $post]);
+ return $feedItem;
}
if (str_starts_with($feedItem->url, 'https://www.youtube.com')) {
diff --git a/app/Services/News/Feeds/RdfFeed.php b/app/Services/News/Feeds/RdfFeed.php
index 54313ad4..f9d608f3 100644
--- a/app/Services/News/Feeds/RdfFeed.php
+++ b/app/Services/News/Feeds/RdfFeed.php
@@ -37,7 +37,7 @@ public function getPhoto(): ?string
public function getName(): string
{
- return $this->element->title;
+ return (string) $this->element->title ?? '';
}
public function getData(): array
@@ -46,7 +46,7 @@ public function getData(): array
foreach ($this->element->item as $post) {
$feedItem = new FeedItem();
- $feedItem->id = $post->guid ?? $post->link;
+ $feedItem->id = (string) ($post->guid ?? $post->link ?? '');
$feedItem->setTitle($post->title);
// This bit could be too specific for other rdf feeds :sweat_smile:
diff --git a/app/Services/SshKeyGeneratorService.php b/app/Services/SshKeyGeneratorService.php
index 44b42d25..6174f04c 100644
--- a/app/Services/SshKeyGeneratorService.php
+++ b/app/Services/SshKeyGeneratorService.php
@@ -5,52 +5,27 @@
namespace App\Services;
use Exception;
+use phpseclib3\Crypt\EC;
+use phpseclib3\Crypt\RSA;
class SshKeyGeneratorService
{
- protected string $privateKey;
-
- protected string $publicKey;
-
/**
* Store an encrypted version of the SSH key on the server, and in the databasae.
*/
- public function __construct(
- private string $curveName = 'prime256v1',
- protected string $privateKeyFile = '',
- protected string $publicKeyFile = '',
- protected bool $overwrite = false,
- protected string $encryptedPrivateKey = '',
- protected string $encryptedPublicKey = '',
- protected string $passKey = '',
+ public static function generate(
+ string $passKey
) {
- $res = openssl_pkey_new([
- 'curve_name' => $this->curveName,
- 'private_key_type' => OPENSSL_KEYTYPE_EC,
- ]);
- if (! $res) {
- throw new Exception('Could not generate the key pair.');
+ $key = EC::createKey('ed25519');
+ if (!empty($passKey)) {
+ $key->withPassword($passKey);
}
- openssl_pkey_export($res, $privKey, $this->passKey);
-
- $this->encryptedPrivateKey = $privKey;
- $pubKeyDetails = openssl_pkey_get_details($res);
- unset($privKey);
- unset($res);
- $this->encryptedPublicKey = $pubKeyDetails['key'];
+ $privateKey = $key->toString('openssh');
+ $publicKey = $key->getPublicKey()->toString('openssh');
- if (! file_exists($this->privateKeyFile)) {
- file_put_contents($this->privateKeyFile, $this->encryptedPrivateKey);
- chmod($this->privateKeyFile, 0600);
- }
-
- if (! file_exists($this->publicKeyFile)) {
- // dd(sprintf('echo "%s"', $this->passKey).' && ssh-keygen -y -f '.$this->privateKeyFile.' > '.$this->publicKeyFile);
- file_put_contents($this->publicKeyFile, $this->encryptedPublicKey);
- chmod($this->publicKeyFile, 0600);
- }
+ return [$privateKey, $publicKey];
}
public function getPrivateKey(): string
diff --git a/app/Services/SshService.php b/app/Services/SshService.php
index e2523bbd..f84524cc 100644
--- a/app/Services/SshService.php
+++ b/app/Services/SshService.php
@@ -30,7 +30,13 @@ public function __construct(
}
// try {
- ssh2_auth_pubkey_file($this->connection, $username, $publicKeyFile, $privateKeyFile, $passKey);
+ ssh2_auth_pubkey_file(
+ $this->connection,
+ $username,
+ $publicKeyFile,
+ $privateKeyFile,
+ $passKey
+ );
// } catch (\Throwable $e) {
// throw new Exception('Public key authentication failed. ' . $this->username . '@' . $this->host . ':' . $this->port);
// }
@@ -64,22 +70,30 @@ public function execute(string $command, string $directory = ''): string
public function run(Script $script, string $directory = ''): array
{
$localFilePath = storage_path('scripts/'.Str::slug($script->name).'_server.sh');
-
+ @mkdir(dirname($localFilePath), 0755, true);
file_put_contents($localFilePath, $script->script);
// Ensure our .basement folder exists
- ssh2_exec($this->connection, 'mkdir /tmp/.spork -f');
- stream_set_blocking($this->connection, true);
+ $exec = ssh2_exec($this->connection, 'mkdir /tmp/.spork -f');
+ stream_set_blocking($exec, true);
// Create a local copy of our script to make sure it runs like we'd expect.
- ssh2_scp_send($this->connection, $localFilePath, $file = '/tmp/.spork/'.Str::random(32).'.sh');
+ ssh2_scp_send($this->connection, $localFilePath, $file = '/tmp/.spork/'.Str::random(32).'.sh', 0644);
unlink($localFilePath);
- // Run a command that will probably write to stderr (unless you have a folder named /hom)
- $stream_out = ssh2_exec($this->connection, 'bash '.escapeshellcmd($file));
-
- $stream_error = ssh2_fetch_stream($this->connection, SSH2_STREAM_STDERR);
- ssh2_exec($this->connection, "rm $file -f");
+ try {
+ // Run a command that will probably write to stderr (unless you have a folder named /hom)
+ $stream_out = ssh2_exec($this->connection, 'bash ' . escapeshellcmd($file). ' 2>&1');
+ stream_set_blocking($stream_out, true);
+
+ $stream_error = ssh2_fetch_stream($stream_out, SSH2_STREAM_STDERR);
+ ssh2_exec($this->connection, "rm $file -f");
+ } catch (\Throwable $e) {
+ return [
+ 'stdout' => '',
+ 'stderr' => $e->getMessage() . "\n" . $e->getTraceAsString(),
+ ];
+ }
return [
'stdout' => stream_get_contents($stream_out),
diff --git a/composer.json b/composer.json
index 5b773bee..cf849ebe 100644
--- a/composer.json
+++ b/composer.json
@@ -20,11 +20,13 @@
"composer/composer": "^2.6",
"guzzlehttp/guzzle": "^7.7",
"inertiajs/inertia-laravel": "^1.0",
+ "kregel/exception-probe": "^1.0",
"laravel-notification-channels/webhook": "^2.6",
"laravel/forge-sdk": "^3.13",
"laravel/framework": "^11.7",
"laravel/horizon": "^5.22",
"laravel/jetstream": "^5.0",
+ "laravel/pulse": "^1.2",
"laravel/reverb": "@beta",
"laravel/sanctum": "^4.0",
"laravel/scout": "^10.8",
@@ -37,6 +39,7 @@
"nativephp/electron": "^0.5.0",
"nette/php-generator": "*",
"php-imap/php-imap": "^5.0",
+ "phpseclib/phpseclib": "*",
"pusher/pusher-php-server": "^7.0",
"smalot/pdfparser": "^2.10",
"spatie/laravel-activitylog": "^4.8",
@@ -53,6 +56,7 @@
"larastan/larastan": "^2.0",
"laravel/pint": "^1.13",
"laravel/sail": "^1.26",
+ "laravel/telescope": "^5.0",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.0",
"phpstan/phpstan": "^1.11",
diff --git a/composer.lock b/composer.lock
index d32c1579..24ba7953 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "81f5969e34e14bf81318c209517cdcf9",
+ "content-hash": "ecca669ba01de29a76248519cb5203bf",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -632,16 +632,16 @@
},
{
"name": "composer/class-map-generator",
- "version": "1.1.1",
+ "version": "1.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/class-map-generator.git",
- "reference": "8286a62d243312ed99b3eee20d5005c961adb311"
+ "reference": "acd227952154850d0bb7d65caa4f9edf9cd806a7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/class-map-generator/zipball/8286a62d243312ed99b3eee20d5005c961adb311",
- "reference": "8286a62d243312ed99b3eee20d5005c961adb311",
+ "url": "https://api.github.com/repos/composer/class-map-generator/zipball/acd227952154850d0bb7d65caa4f9edf9cd806a7",
+ "reference": "acd227952154850d0bb7d65caa4f9edf9cd806a7",
"shasum": ""
},
"require": {
@@ -685,7 +685,7 @@
],
"support": {
"issues": "https://github.com/composer/class-map-generator/issues",
- "source": "https://github.com/composer/class-map-generator/tree/1.1.1"
+ "source": "https://github.com/composer/class-map-generator/tree/1.3.2"
},
"funding": [
{
@@ -701,7 +701,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-15T12:53:41+00:00"
+ "time": "2024-05-31T19:45:56+00:00"
},
{
"name": "composer/composer",
@@ -888,16 +888,16 @@
},
{
"name": "composer/pcre",
- "version": "3.1.3",
+ "version": "3.1.4",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
- "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
+ "reference": "04229f163664973f68f38f6f73d917799168ef24"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
- "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/04229f163664973f68f38f6f73d917799168ef24",
+ "reference": "04229f163664973f68f38f6f73d917799168ef24",
"shasum": ""
},
"require": {
@@ -939,7 +939,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/3.1.3"
+ "source": "https://github.com/composer/pcre/tree/3.1.4"
},
"funding": [
{
@@ -955,7 +955,7 @@
"type": "tidelift"
}
],
- "time": "2024-03-19T10:26:25+00:00"
+ "time": "2024-05-27T13:40:54+00:00"
},
{
"name": "composer/semver",
@@ -1477,6 +1477,61 @@
],
"time": "2024-02-05T11:56:58+00:00"
},
+ {
+ "name": "doctrine/sql-formatter",
+ "version": "1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/sql-formatter.git",
+ "reference": "d1ac84aef745c69ea034929eb6d65a6908b675cc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d1ac84aef745c69ea034929eb6d65a6908b675cc",
+ "reference": "d1ac84aef745c69ea034929eb6d65a6908b675cc",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.5",
+ "vimeo/psalm": "^5.24"
+ },
+ "bin": [
+ "bin/sql-formatter"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\SqlFormatter\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jeremy Dorn",
+ "email": "jeremy@jeremydorn.com",
+ "homepage": "https://jeremydorn.com/"
+ }
+ ],
+ "description": "a PHP SQL highlighting library",
+ "homepage": "https://github.com/doctrine/sql-formatter/",
+ "keywords": [
+ "highlight",
+ "sql"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/sql-formatter/issues",
+ "source": "https://github.com/doctrine/sql-formatter/tree/1.4.0"
+ },
+ "time": "2024-05-08T08:12:09+00:00"
+ },
{
"name": "dragonmantank/cron-expression",
"version": "v3.3.3",
@@ -2277,12 +2332,12 @@
"version": "v5.2.13",
"source": {
"type": "git",
- "url": "https://github.com/justinrainbow/json-schema.git",
+ "url": "https://github.com/jsonrainbow/json-schema.git",
"reference": "fbbe7e5d79f618997bc3332a6f49246036c45793"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793",
+ "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793",
"reference": "fbbe7e5d79f618997bc3332a6f49246036c45793",
"shasum": ""
},
@@ -2337,11 +2392,74 @@
"schema"
],
"support": {
- "issues": "https://github.com/justinrainbow/json-schema/issues",
- "source": "https://github.com/justinrainbow/json-schema/tree/v5.2.13"
+ "issues": "https://github.com/jsonrainbow/json-schema/issues",
+ "source": "https://github.com/jsonrainbow/json-schema/tree/v5.2.13"
},
"time": "2023-09-26T02:20:38+00:00"
},
+ {
+ "name": "kregel/exception-probe",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/austinkregel/php-exception-probe.git",
+ "reference": "8961f446feb57d7aeb830163ba04faa07cd213fd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/austinkregel/php-exception-probe/zipball/8961f446feb57d7aeb830163ba04faa07cd213fd",
+ "reference": "8961f446feb57d7aeb830163ba04faa07cd213fd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Kregel\\ExceptionProbe\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Austin Kregel",
+ "email": "github@austinkregel.com",
+ "homepage": "https://austinkregel.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "A package to help get more information from stack traces, and exceptions",
+ "homepage": "https://github.com/kregel/php-exception-probe",
+ "keywords": [
+ "php-exception-probe"
+ ],
+ "support": {
+ "issues": "https://github.com/austinkregel/php-exception-probe/issues",
+ "source": "https://github.com/austinkregel/php-exception-probe/tree/v1.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://beerpay.io/austinkregel/php-exception-probe",
+ "type": "custom"
+ },
+ {
+ "url": "https://ko-fi.com/kregel",
+ "type": "ko_fi"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/composer/exception-probe",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-03-17T23:33:13+00:00"
+ },
{
"name": "laravel-notification-channels/webhook",
"version": "2.6.0",
@@ -2532,16 +2650,16 @@
},
{
"name": "laravel/framework",
- "version": "v11.8.0",
+ "version": "v11.9.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "ceb892a25817c888ef3df4d1a2af9cac53978300"
+ "reference": "2b3e8d75f10b0ed17416282946355dc026bf326c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/ceb892a25817c888ef3df4d1a2af9cac53978300",
- "reference": "ceb892a25817c888ef3df4d1a2af9cac53978300",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/2b3e8d75f10b0ed17416282946355dc026bf326c",
+ "reference": "2b3e8d75f10b0ed17416282946355dc026bf326c",
"shasum": ""
},
"require": {
@@ -2733,7 +2851,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2024-05-21T17:57:45+00:00"
+ "time": "2024-05-30T09:40:11+00:00"
},
{
"name": "laravel/horizon",
@@ -2883,16 +3001,16 @@
},
{
"name": "laravel/prompts",
- "version": "v0.1.22",
+ "version": "v0.1.23",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
- "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5"
+ "reference": "9bc4df7c699b0452c6b815e64a2d84b6d7f99400"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/prompts/zipball/37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
- "reference": "37f94de71758dbfbccc9d299b0e5eb76e02a40f5",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/9bc4df7c699b0452c6b815e64a2d84b6d7f99400",
+ "reference": "9bc4df7c699b0452c6b815e64a2d84b6d7f99400",
"shasum": ""
},
"require": {
@@ -2935,22 +3053,109 @@
"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.22"
+ "source": "https://github.com/laravel/prompts/tree/v0.1.23"
},
- "time": "2024-05-10T19:22:18+00:00"
+ "time": "2024-05-27T13:53:20+00:00"
+ },
+ {
+ "name": "laravel/pulse",
+ "version": "v1.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/pulse.git",
+ "reference": "6add38347003ee602a4c5c2a7cb920c092ac3a25"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/pulse/zipball/6add38347003ee602a4c5c2a7cb920c092ac3a25",
+ "reference": "6add38347003ee602a4c5c2a7cb920c092ac3a25",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/sql-formatter": "^1.2",
+ "guzzlehttp/promises": "^1.0|^2.0",
+ "illuminate/auth": "^10.48.4|^11.0.8",
+ "illuminate/cache": "^10.48.4|^11.0.8",
+ "illuminate/config": "^10.48.4|^11.0.8",
+ "illuminate/console": "^10.48.4|^11.0.8",
+ "illuminate/contracts": "^10.48.4|^11.0.8",
+ "illuminate/database": "^10.48.4|^11.0.8",
+ "illuminate/events": "^10.48.4|^11.0.8",
+ "illuminate/http": "^10.48.4|^11.0.8",
+ "illuminate/queue": "^10.48.4|^11.0.8",
+ "illuminate/redis": "^10.48.4|^11.0.8",
+ "illuminate/routing": "^10.48.4|^11.0.8",
+ "illuminate/support": "^10.48.4|^11.0.8",
+ "illuminate/view": "^10.48.4|^11.0.8",
+ "livewire/livewire": "^3.4.9",
+ "nesbot/carbon": "^2.67|^3.0",
+ "php": "^8.1",
+ "symfony/console": "^6.0|^7.0"
+ },
+ "conflict": {
+ "nunomaduro/collision": "<7.7.0"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^7.7",
+ "mockery/mockery": "^1.0",
+ "orchestra/testbench": "^8.23.1|^9.0",
+ "pestphp/pest": "^2.0",
+ "pestphp/pest-plugin-laravel": "^2.2",
+ "phpstan/phpstan": "^1.11",
+ "predis/predis": "^1.0|^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Laravel\\Pulse\\PulseServiceProvider"
+ ],
+ "aliases": {
+ "Pulse": "Laravel\\Pulse\\Facades\\Pulse"
+ }
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laravel\\Pulse\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ }
+ ],
+ "description": "Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.",
+ "homepage": "https://github.com/laravel/pulse",
+ "keywords": [
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/pulse/issues",
+ "source": "https://github.com/laravel/pulse"
+ },
+ "time": "2024-05-26T23:09:52+00:00"
},
{
"name": "laravel/reverb",
- "version": "v1.0.0-beta11",
+ "version": "v1.0.0-beta12",
"source": {
"type": "git",
"url": "https://github.com/laravel/reverb.git",
- "reference": "f0cee423dce0ed8c8d65dbfdfc531b188627a50d"
+ "reference": "513fc427e86c66dfc0042e0c58243d80480c1e3d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/reverb/zipball/f0cee423dce0ed8c8d65dbfdfc531b188627a50d",
- "reference": "f0cee423dce0ed8c8d65dbfdfc531b188627a50d",
+ "url": "https://api.github.com/repos/laravel/reverb/zipball/513fc427e86c66dfc0042e0c58243d80480c1e3d",
+ "reference": "513fc427e86c66dfc0042e0c58243d80480c1e3d",
"shasum": ""
},
"require": {
@@ -2964,6 +3169,7 @@
"php": "^8.2",
"pusher/pusher-php-server": "^7.2",
"ratchet/rfc6455": "^0.3.1",
+ "react/async": "^4.2",
"react/promise-timer": "^1.10",
"react/socket": "^1.14",
"symfony/console": "^6.0|^7.0",
@@ -2974,7 +3180,6 @@
"pestphp/pest": "^2.0",
"phpstan/phpstan": "^1.10",
"ratchet/pawl": "^0.4.1",
- "react/async": "^4.0",
"react/http": "^1.9"
},
"type": "library",
@@ -3017,9 +3222,9 @@
],
"support": {
"issues": "https://github.com/laravel/reverb/issues",
- "source": "https://github.com/laravel/reverb/tree/v1.0.0-beta11"
+ "source": "https://github.com/laravel/reverb/tree/v1.0.0-beta12"
},
- "time": "2024-05-09T17:23:01+00:00"
+ "time": "2024-05-27T13:55:38+00:00"
},
{
"name": "laravel/sanctum",
@@ -3479,16 +3684,16 @@
},
{
"name": "league/flysystem",
- "version": "3.27.0",
+ "version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
- "reference": "4729745b1ab737908c7d055148c9a6b3e959832f"
+ "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4729745b1ab737908c7d055148c9a6b3e959832f",
- "reference": "4729745b1ab737908c7d055148c9a6b3e959832f",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c",
+ "reference": "e611adab2b1ae2e3072fa72d62c62f52c2bf1f0c",
"shasum": ""
},
"require": {
@@ -3512,10 +3717,13 @@
"composer/semver": "^3.0",
"ext-fileinfo": "*",
"ext-ftp": "*",
+ "ext-mongodb": "^1.3",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.5",
"google/cloud-storage": "^1.23",
+ "guzzlehttp/psr7": "^2.6",
"microsoft/azure-storage-blob": "^1.1",
+ "mongodb/mongodb": "^1.2",
"phpseclib/phpseclib": "^3.0.36",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.5.11|^10.0",
@@ -3553,32 +3761,22 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
- "source": "https://github.com/thephpleague/flysystem/tree/3.27.0"
+ "source": "https://github.com/thephpleague/flysystem/tree/3.28.0"
},
- "funding": [
- {
- "url": "https://ecologi.com/frankdejonge",
- "type": "custom"
- },
- {
- "url": "https://github.com/frankdejonge",
- "type": "github"
- }
- ],
- "time": "2024-04-07T19:17:50+00:00"
+ "time": "2024-05-22T10:09:12+00:00"
},
{
"name": "league/flysystem-ftp",
- "version": "3.27.0",
+ "version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-ftp.git",
- "reference": "92ce9075318ede9ec6eef54d0c13654febba5893"
+ "reference": "6c65e1de3767dca7f2712571a915cb952bae42e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem-ftp/zipball/92ce9075318ede9ec6eef54d0c13654febba5893",
- "reference": "92ce9075318ede9ec6eef54d0c13654febba5893",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-ftp/zipball/6c65e1de3767dca7f2712571a915cb952bae42e0",
+ "reference": "6c65e1de3767dca7f2712571a915cb952bae42e0",
"shasum": ""
},
"require": {
@@ -3613,32 +3811,22 @@
"ftpd"
],
"support": {
- "source": "https://github.com/thephpleague/flysystem-ftp/tree/3.27.0"
+ "source": "https://github.com/thephpleague/flysystem-ftp/tree/3.28.0"
},
- "funding": [
- {
- "url": "https://ecologi.com/frankdejonge",
- "type": "custom"
- },
- {
- "url": "https://github.com/frankdejonge",
- "type": "github"
- }
- ],
- "time": "2024-04-07T12:08:10+00:00"
+ "time": "2024-05-06T20:05:52+00:00"
},
{
"name": "league/flysystem-local",
- "version": "3.25.1",
+ "version": "3.28.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-local.git",
- "reference": "61a6a90d6e999e4ddd9ce5adb356de0939060b92"
+ "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/61a6a90d6e999e4ddd9ce5adb356de0939060b92",
- "reference": "61a6a90d6e999e4ddd9ce5adb356de0939060b92",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/13f22ea8be526ea58c2ddff9e158ef7c296e4f40",
+ "reference": "13f22ea8be526ea58c2ddff9e158ef7c296e4f40",
"shasum": ""
},
"require": {
@@ -3672,19 +3860,9 @@
"local"
],
"support": {
- "source": "https://github.com/thephpleague/flysystem-local/tree/3.25.1"
+ "source": "https://github.com/thephpleague/flysystem-local/tree/3.28.0"
},
- "funding": [
- {
- "url": "https://ecologi.com/frankdejonge",
- "type": "custom"
- },
- {
- "url": "https://github.com/frankdejonge",
- "type": "github"
- }
- ],
- "time": "2024-03-15T19:58:44+00:00"
+ "time": "2024-05-06T20:05:52+00:00"
},
{
"name": "league/mime-type-detection",
@@ -3809,6 +3987,82 @@
},
"time": "2024-03-24T12:31:56+00:00"
},
+ {
+ "name": "livewire/livewire",
+ "version": "v3.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/livewire/livewire.git",
+ "reference": "72e900825c560f0e4e620185b26c5441a8914435"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/72e900825c560f0e4e620185b26c5441a8914435",
+ "reference": "72e900825c560f0e4e620185b26c5441a8914435",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/database": "^10.0|^11.0",
+ "illuminate/routing": "^10.0|^11.0",
+ "illuminate/support": "^10.0|^11.0",
+ "illuminate/validation": "^10.0|^11.0",
+ "league/mime-type-detection": "^1.9",
+ "php": "^8.1",
+ "symfony/console": "^6.0|^7.0",
+ "symfony/http-kernel": "^6.2|^7.0"
+ },
+ "require-dev": {
+ "calebporzio/sushi": "^2.1",
+ "laravel/framework": "^10.15.0|^11.0",
+ "laravel/prompts": "^0.1.6",
+ "mockery/mockery": "^1.3.1",
+ "orchestra/testbench": "^8.21.0|^9.0",
+ "orchestra/testbench-dusk": "^8.24|^9.1",
+ "phpunit/phpunit": "^10.4",
+ "psy/psysh": "^0.11.22|^0.12"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Livewire\\LivewireServiceProvider"
+ ],
+ "aliases": {
+ "Livewire": "Livewire\\Livewire"
+ }
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Livewire\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Caleb Porzio",
+ "email": "calebporzio@gmail.com"
+ }
+ ],
+ "description": "A front-end framework for Laravel.",
+ "support": {
+ "issues": "https://github.com/livewire/livewire/issues",
+ "source": "https://github.com/livewire/livewire/tree/v3.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/livewire",
+ "type": "github"
+ }
+ ],
+ "time": "2024-05-21T13:39:04+00:00"
+ },
{
"name": "meilisearch/meilisearch-php",
"version": "v1.8.0",
@@ -4436,16 +4690,16 @@
},
{
"name": "nesbot/carbon",
- "version": "3.3.1",
+ "version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "8ff64b92c1b1ec84fcde9f8bb9ff2ca34cb8a77a"
+ "reference": "8eab8983c83c30e0bacbef8d311e3f3b8172727f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8ff64b92c1b1ec84fcde9f8bb9ff2ca34cb8a77a",
- "reference": "8ff64b92c1b1ec84fcde9f8bb9ff2ca34cb8a77a",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8eab8983c83c30e0bacbef8d311e3f3b8172727f",
+ "reference": "8eab8983c83c30e0bacbef8d311e3f3b8172727f",
"shasum": ""
},
"require": {
@@ -4538,7 +4792,7 @@
"type": "tidelift"
}
],
- "time": "2024-05-01T06:54:22+00:00"
+ "time": "2024-05-24T14:26:34+00:00"
},
{
"name": "netresearch/jsonmapper",
@@ -5628,6 +5882,116 @@
],
"time": "2023-11-12T21:59:55+00:00"
},
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "3.0.37",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
+ "reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/constant_time_encoding": "^1|^2",
+ "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
+ "php": ">=5.6.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "suggest": {
+ "ext-dom": "Install the DOM extension to load XML formatted public keys.",
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib3\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "homepage": "http://phpseclib.sourceforge.net",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ],
+ "support": {
+ "issues": "https://github.com/phpseclib/phpseclib/issues",
+ "source": "https://github.com/phpseclib/phpseclib/tree/3.0.37"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/terrafrost",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/phpseclib",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-03-03T02:14:58+00:00"
+ },
{
"name": "pragmarx/google2fa",
"version": "v8.0.1",
@@ -6514,6 +6878,81 @@
},
"time": "2021-12-09T23:20:49+00:00"
},
+ {
+ "name": "react/async",
+ "version": "v4.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/async.git",
+ "reference": "7c3738e837b38c9513af44398b8c1b2b1be1fbbc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/async/zipball/7c3738e837b38c9513af44398b8c1b2b1be1fbbc",
+ "reference": "7c3738e837b38c9513af44398b8c1b2b1be1fbbc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "react/event-loop": "^1.2",
+ "react/promise": "^3.0 || ^2.8 || ^1.2.1"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "1.10.39",
+ "phpunit/phpunit": "^9.6"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "React\\Async\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering",
+ "homepage": "https://clue.engineering/"
+ },
+ {
+ "name": "Cees-Jan Kiewiet",
+ "email": "reactphp@ceesjankiewiet.nl",
+ "homepage": "https://wyrihaximus.net/"
+ },
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com",
+ "homepage": "https://sorgalla.com/"
+ },
+ {
+ "name": "Chris Boden",
+ "email": "cboden@gmail.com",
+ "homepage": "https://cboden.dev/"
+ }
+ ],
+ "description": "Async utilities and fibers for ReactPHP",
+ "keywords": [
+ "async",
+ "reactphp"
+ ],
+ "support": {
+ "issues": "https://github.com/reactphp/async/issues",
+ "source": "https://github.com/reactphp/async/tree/v4.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/reactphp",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2023-11-22T16:43:46+00:00"
+ },
{
"name": "react/cache",
"version": "v1.2.0",
@@ -6736,16 +7175,16 @@
},
{
"name": "react/promise",
- "version": "v3.1.0",
+ "version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/promise.git",
- "reference": "e563d55d1641de1dea9f5e84f3cccc66d2bfe02c"
+ "reference": "8a164643313c71354582dc850b42b33fa12a4b63"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/reactphp/promise/zipball/e563d55d1641de1dea9f5e84f3cccc66d2bfe02c",
- "reference": "e563d55d1641de1dea9f5e84f3cccc66d2bfe02c",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63",
+ "reference": "8a164643313c71354582dc850b42b33fa12a4b63",
"shasum": ""
},
"require": {
@@ -6797,7 +7236,7 @@
],
"support": {
"issues": "https://github.com/reactphp/promise/issues",
- "source": "https://github.com/reactphp/promise/tree/v3.1.0"
+ "source": "https://github.com/reactphp/promise/tree/v3.2.0"
},
"funding": [
{
@@ -6805,7 +7244,7 @@
"type": "open_collective"
}
],
- "time": "2023-11-16T16:21:57+00:00"
+ "time": "2024-05-24T10:39:05+00:00"
},
{
"name": "react/promise-timer",
@@ -7407,16 +7846,16 @@
},
{
"name": "spatie/flare-client-php",
- "version": "1.5.1",
+ "version": "1.6.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/flare-client-php.git",
- "reference": "e27977d534eefe04c154c6fd8460217024054c05"
+ "reference": "220a7c8745e9fa427d54099f47147c4b97fe6462"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/e27977d534eefe04c154c6fd8460217024054c05",
- "reference": "e27977d534eefe04c154c6fd8460217024054c05",
+ "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/220a7c8745e9fa427d54099f47147c4b97fe6462",
+ "reference": "220a7c8745e9fa427d54099f47147c4b97fe6462",
"shasum": ""
},
"require": {
@@ -7464,7 +7903,7 @@
],
"support": {
"issues": "https://github.com/spatie/flare-client-php/issues",
- "source": "https://github.com/spatie/flare-client-php/tree/1.5.1"
+ "source": "https://github.com/spatie/flare-client-php/tree/1.6.0"
},
"funding": [
{
@@ -7472,20 +7911,20 @@
"type": "github"
}
],
- "time": "2024-05-03T15:43:14+00:00"
+ "time": "2024-05-22T09:45:39+00:00"
},
{
"name": "spatie/ignition",
- "version": "1.14.1",
+ "version": "1.14.2",
"source": {
"type": "git",
"url": "https://github.com/spatie/ignition.git",
- "reference": "c23cc018c5f423d2f413b99f84655fceb6549811"
+ "reference": "5e11c11f675bb5251f061491a493e04a1a571532"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/ignition/zipball/c23cc018c5f423d2f413b99f84655fceb6549811",
- "reference": "c23cc018c5f423d2f413b99f84655fceb6549811",
+ "url": "https://api.github.com/repos/spatie/ignition/zipball/5e11c11f675bb5251f061491a493e04a1a571532",
+ "reference": "5e11c11f675bb5251f061491a493e04a1a571532",
"shasum": ""
},
"require": {
@@ -7555,7 +7994,7 @@
"type": "github"
}
],
- "time": "2024-05-03T15:56:16+00:00"
+ "time": "2024-05-29T08:10:20+00:00"
},
{
"name": "spatie/laravel-activitylog",
@@ -8304,16 +8743,16 @@
},
{
"name": "symfony/clock",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/clock.git",
- "reference": "2008671acb4a30b01c453de193cf9c80549ebda6"
+ "reference": "fe47b7cf6a68c045c37928aa89a39d5eb9a2b37c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/clock/zipball/2008671acb4a30b01c453de193cf9c80549ebda6",
- "reference": "2008671acb4a30b01c453de193cf9c80549ebda6",
+ "url": "https://api.github.com/repos/symfony/clock/zipball/fe47b7cf6a68c045c37928aa89a39d5eb9a2b37c",
+ "reference": "fe47b7cf6a68c045c37928aa89a39d5eb9a2b37c",
"shasum": ""
},
"require": {
@@ -8358,7 +8797,7 @@
"time"
],
"support": {
- "source": "https://github.com/symfony/clock/tree/v7.0.7"
+ "source": "https://github.com/symfony/clock/tree/v7.1.0"
},
"funding": [
{
@@ -8374,20 +8813,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/console",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "c981e0e9380ce9f146416bde3150c79197ce9986"
+ "reference": "5bcde9e0b2ea9bd9772bca17618365ea921c5707"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/c981e0e9380ce9f146416bde3150c79197ce9986",
- "reference": "c981e0e9380ce9f146416bde3150c79197ce9986",
+ "url": "https://api.github.com/repos/symfony/console/zipball/5bcde9e0b2ea9bd9772bca17618365ea921c5707",
+ "reference": "5bcde9e0b2ea9bd9772bca17618365ea921c5707",
"shasum": ""
},
"require": {
@@ -8451,7 +8890,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.0.7"
+ "source": "https://github.com/symfony/console/tree/v7.1.0"
},
"funding": [
{
@@ -8467,20 +8906,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-17T10:55:18+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc"
+ "reference": "843f2f7ac5e4c5bf0ec77daef23ca6d4d8922adc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc",
- "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/843f2f7ac5e4c5bf0ec77daef23ca6d4d8922adc",
+ "reference": "843f2f7ac5e4c5bf0ec77daef23ca6d4d8922adc",
"shasum": ""
},
"require": {
@@ -8516,7 +8955,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v7.0.7"
+ "source": "https://github.com/symfony/css-selector/tree/v7.1.0"
},
"funding": [
{
@@ -8532,7 +8971,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -8603,16 +9042,16 @@
},
{
"name": "symfony/error-handler",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "cf97429887e40480c847bfeb6c3991e1e2c086ab"
+ "reference": "477d911900bf32fc43a675f78d4cbaedbb78378f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf97429887e40480c847bfeb6c3991e1e2c086ab",
- "reference": "cf97429887e40480c847bfeb6c3991e1e2c086ab",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/477d911900bf32fc43a675f78d4cbaedbb78378f",
+ "reference": "477d911900bf32fc43a675f78d4cbaedbb78378f",
"shasum": ""
},
"require": {
@@ -8658,7 +9097,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/v7.0.7"
+ "source": "https://github.com/symfony/error-handler/tree/v7.1.0"
},
"funding": [
{
@@ -8674,20 +9113,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-17T10:55:18+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9"
+ "reference": "522d2772d6c7bab843b0c52466dc7844622bacc2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db2a7fab994d67d92356bb39c367db115d9d30f9",
- "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/522d2772d6c7bab843b0c52466dc7844622bacc2",
+ "reference": "522d2772d6c7bab843b0c52466dc7844622bacc2",
"shasum": ""
},
"require": {
@@ -8738,7 +9177,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/v7.0.7"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.0"
},
"funding": [
{
@@ -8754,7 +9193,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -8834,22 +9273,24 @@
},
{
"name": "symfony/filesystem",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "cc168be6fbdcdf3401f50ae863ee3818ed4338f5"
+ "reference": "8ecdde25881598f86cdd7cfe8b25302b66a402e9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/cc168be6fbdcdf3401f50ae863ee3818ed4338f5",
- "reference": "cc168be6fbdcdf3401f50ae863ee3818ed4338f5",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/8ecdde25881598f86cdd7cfe8b25302b66a402e9",
+ "reference": "8ecdde25881598f86cdd7cfe8b25302b66a402e9",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-mbstring": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "require-dev": {
"symfony/process": "^6.4|^7.0"
},
"type": "library",
@@ -8878,7 +9319,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.0.7"
+ "source": "https://github.com/symfony/filesystem/tree/v7.1.0"
},
"funding": [
{
@@ -8894,20 +9335,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-17T10:55:18+00:00"
},
{
"name": "symfony/finder",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "4d58f0f4fe95a30d7b538d71197135483560b97c"
+ "reference": "fb6c2d65c3dbf7ad83201a4168d4510c8dddaac7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/4d58f0f4fe95a30d7b538d71197135483560b97c",
- "reference": "4d58f0f4fe95a30d7b538d71197135483560b97c",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/fb6c2d65c3dbf7ad83201a4168d4510c8dddaac7",
+ "reference": "fb6c2d65c3dbf7ad83201a4168d4510c8dddaac7",
"shasum": ""
},
"require": {
@@ -8942,7 +9383,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.0.7"
+ "source": "https://github.com/symfony/finder/tree/v7.1.0"
},
"funding": [
{
@@ -8958,20 +9399,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-28T11:44:19+00:00"
+ "time": "2024-04-28T18:29:00+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "0194e064b8bdc29381462f790bab04e1cac8fdc8"
+ "reference": "f9c54a6b1697d0b3b3d541e89e7843cdb3c9bfb7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0194e064b8bdc29381462f790bab04e1cac8fdc8",
- "reference": "0194e064b8bdc29381462f790bab04e1cac8fdc8",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f9c54a6b1697d0b3b3d541e89e7843cdb3c9bfb7",
+ "reference": "f9c54a6b1697d0b3b3d541e89e7843cdb3c9bfb7",
"shasum": ""
},
"require": {
@@ -9019,7 +9460,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.0.7"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.1.0"
},
"funding": [
{
@@ -9035,25 +9476,26 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-20T16:41:11+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "e07bb9bd86e7cd8ba2d3d9c618eec9d1bbe06d25"
+ "reference": "7eb093ee3911354aa13704d757127535dd8d371f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/e07bb9bd86e7cd8ba2d3d9c618eec9d1bbe06d25",
- "reference": "e07bb9bd86e7cd8ba2d3d9c618eec9d1bbe06d25",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/7eb093ee3911354aa13704d757127535dd8d371f",
+ "reference": "7eb093ee3911354aa13704d757127535dd8d371f",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/log": "^1|^2|^3",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/error-handler": "^6.4|^7.0",
"symfony/event-dispatcher": "^6.4|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
@@ -9094,9 +9536,9 @@
"symfony/finder": "^6.4|^7.0",
"symfony/http-client-contracts": "^2.5|^3",
"symfony/process": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-access": "^7.1",
"symfony/routing": "^6.4|^7.0",
- "symfony/serializer": "^6.4.4|^7.0.4",
+ "symfony/serializer": "^7.1",
"symfony/stopwatch": "^6.4|^7.0",
"symfony/translation": "^6.4|^7.0",
"symfony/translation-contracts": "^2.5|^3",
@@ -9132,7 +9574,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/v7.0.7"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.1.0"
},
"funding": [
{
@@ -9148,20 +9590,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-29T12:20:25+00:00"
+ "time": "2024-05-31T07:46:30+00:00"
},
{
"name": "symfony/mailer",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "4ff41a7c7998a88cfdc31b5841ef64d9246fc56a"
+ "reference": "1528f3fb85d1cbed8bf68a19d5428de662c29d7e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/4ff41a7c7998a88cfdc31b5841ef64d9246fc56a",
- "reference": "4ff41a7c7998a88cfdc31b5841ef64d9246fc56a",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/1528f3fb85d1cbed8bf68a19d5428de662c29d7e",
+ "reference": "1528f3fb85d1cbed8bf68a19d5428de662c29d7e",
"shasum": ""
},
"require": {
@@ -9212,7 +9654,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v7.0.7"
+ "source": "https://github.com/symfony/mailer/tree/v7.1.0"
},
"funding": [
{
@@ -9228,20 +9670,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-31T07:45:05+00:00"
},
{
"name": "symfony/mime",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "3adbf110c306546f6f00337f421d2edca0e8d3c0"
+ "reference": "92d6b9b1217eebff2035577db505b7e1435ca78c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/3adbf110c306546f6f00337f421d2edca0e8d3c0",
- "reference": "3adbf110c306546f6f00337f421d2edca0e8d3c0",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/92d6b9b1217eebff2035577db505b7e1435ca78c",
+ "reference": "92d6b9b1217eebff2035577db505b7e1435ca78c",
"shasum": ""
},
"require": {
@@ -9296,7 +9738,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v7.0.7"
+ "source": "https://github.com/symfony/mime/tree/v7.1.0"
},
"funding": [
{
@@ -9312,20 +9754,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-29T15:16:11+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "23cc173858776ad451e31f053b1c9f47840b2cfa"
+ "reference": "9564f64c16f99e29f252eafc642965e8fcb755ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/23cc173858776ad451e31f053b1c9f47840b2cfa",
- "reference": "23cc173858776ad451e31f053b1c9f47840b2cfa",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/9564f64c16f99e29f252eafc642965e8fcb755ce",
+ "reference": "9564f64c16f99e29f252eafc642965e8fcb755ce",
"shasum": ""
},
"require": {
@@ -9363,7 +9805,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.0.7"
+ "source": "https://github.com/symfony/options-resolver/tree/v7.1.0"
},
"funding": [
{
@@ -9379,7 +9821,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -10246,16 +10688,16 @@
},
{
"name": "symfony/process",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "3839e56b94dd1dbd13235d27504e66baf23faba0"
+ "reference": "56c8a1ea51eb70003fee94a78c7d6d0f44832ce7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/3839e56b94dd1dbd13235d27504e66baf23faba0",
- "reference": "3839e56b94dd1dbd13235d27504e66baf23faba0",
+ "url": "https://api.github.com/repos/symfony/process/zipball/56c8a1ea51eb70003fee94a78c7d6d0f44832ce7",
+ "reference": "56c8a1ea51eb70003fee94a78c7d6d0f44832ce7",
"shasum": ""
},
"require": {
@@ -10287,7 +10729,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.0.7"
+ "source": "https://github.com/symfony/process/tree/v7.1.0"
},
"funding": [
{
@@ -10303,20 +10745,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-17T10:55:18+00:00"
},
{
"name": "symfony/routing",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b"
+ "reference": "0ec2f36fbd769467f98c9c02cea1b76ed117115d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b",
- "reference": "9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/0ec2f36fbd769467f98c9c02cea1b76ed117115d",
+ "reference": "0ec2f36fbd769467f98c9c02cea1b76ed117115d",
"shasum": ""
},
"require": {
@@ -10368,7 +10810,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v7.0.7"
+ "source": "https://github.com/symfony/routing/tree/v7.1.0"
},
"funding": [
{
@@ -10384,7 +10826,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-28T06:54:05+00:00"
},
{
"name": "symfony/service-contracts",
@@ -10471,16 +10913,16 @@
},
{
"name": "symfony/string",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63"
+ "reference": "6f41b185e742737917e6f2e3eca37767fba5f17a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/e405b5424dc2528e02e31ba26b83a79fd4eb8f63",
- "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63",
+ "url": "https://api.github.com/repos/symfony/string/zipball/6f41b185e742737917e6f2e3eca37767fba5f17a",
+ "reference": "6f41b185e742737917e6f2e3eca37767fba5f17a",
"shasum": ""
},
"require": {
@@ -10494,6 +10936,7 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
+ "symfony/emoji": "^7.1",
"symfony/error-handler": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/intl": "^6.4|^7.0",
@@ -10537,7 +10980,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.0.7"
+ "source": "https://github.com/symfony/string/tree/v7.1.0"
},
"funding": [
{
@@ -10553,20 +10996,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-17T10:55:18+00:00"
},
{
"name": "symfony/translation",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "1515e03afaa93e6419aba5d5c9d209159317100b"
+ "reference": "583d18e461eada8270ca44b7d99f07abf1ab048e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/1515e03afaa93e6419aba5d5c9d209159317100b",
- "reference": "1515e03afaa93e6419aba5d5c9d209159317100b",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/583d18e461eada8270ca44b7d99f07abf1ab048e",
+ "reference": "583d18e461eada8270ca44b7d99f07abf1ab048e",
"shasum": ""
},
"require": {
@@ -10631,7 +11074,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v7.0.7"
+ "source": "https://github.com/symfony/translation/tree/v7.1.0"
},
"funding": [
{
@@ -10647,7 +11090,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-02T11:50:05+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -10729,16 +11172,16 @@
},
{
"name": "symfony/uid",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/uid.git",
- "reference": "4f3a5d181999e25918586c8369de09e7814e7be2"
+ "reference": "3bbcb15f311b86f72486826ade080d8013231f96"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/uid/zipball/4f3a5d181999e25918586c8369de09e7814e7be2",
- "reference": "4f3a5d181999e25918586c8369de09e7814e7be2",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/3bbcb15f311b86f72486826ade080d8013231f96",
+ "reference": "3bbcb15f311b86f72486826ade080d8013231f96",
"shasum": ""
},
"require": {
@@ -10783,7 +11226,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/uid/tree/v7.0.7"
+ "source": "https://github.com/symfony/uid/tree/v7.1.0"
},
"funding": [
{
@@ -10799,20 +11242,20 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "d1627b66fd87c8b4d90cabe5671c29d575690924"
+ "reference": "595e4a4bc2118e7f4884315a684678b9403d44a6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d1627b66fd87c8b4d90cabe5671c29d575690924",
- "reference": "d1627b66fd87c8b4d90cabe5671c29d575690924",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/595e4a4bc2118e7f4884315a684678b9403d44a6",
+ "reference": "595e4a4bc2118e7f4884315a684678b9403d44a6",
"shasum": ""
},
"require": {
@@ -10866,7 +11309,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.0.7"
+ "source": "https://github.com/symfony/var-dumper/tree/v7.1.0"
},
"funding": [
{
@@ -10882,7 +11325,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-18T09:29:19+00:00"
+ "time": "2024-05-28T06:54:05+00:00"
},
{
"name": "tightenco/ziggy",
@@ -11411,16 +11854,16 @@
},
{
"name": "larastan/larastan",
- "version": "v2.9.6",
+ "version": "v2.9.7",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
- "reference": "93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f"
+ "reference": "5c805f636095cc2e0b659e3954775cf8f1dad1bb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/larastan/larastan/zipball/93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f",
- "reference": "93d5b95d2e29cdb8203363d44abfdbc0bc7ef57f",
+ "url": "https://api.github.com/repos/larastan/larastan/zipball/5c805f636095cc2e0b659e3954775cf8f1dad1bb",
+ "reference": "5c805f636095cc2e0b659e3954775cf8f1dad1bb",
"shasum": ""
},
"require": {
@@ -11434,7 +11877,7 @@
"illuminate/support": "^9.52.16 || ^10.28.0 || ^11.0",
"php": "^8.0.2",
"phpmyadmin/sql-parser": "^5.9.0",
- "phpstan/phpstan": "^1.10.66"
+ "phpstan/phpstan": "^1.11.1"
},
"require-dev": {
"doctrine/coding-standard": "^12.0",
@@ -11489,7 +11932,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
- "source": "https://github.com/larastan/larastan/tree/v2.9.6"
+ "source": "https://github.com/larastan/larastan/tree/v2.9.7"
},
"funding": [
{
@@ -11509,7 +11952,7 @@
"type": "patreon"
}
],
- "time": "2024-05-09T11:53:26+00:00"
+ "time": "2024-05-27T18:33:26+00:00"
},
{
"name": "laravel/pint",
@@ -11640,6 +12083,75 @@
},
"time": "2024-05-16T21:39:11+00:00"
},
+ {
+ "name": "laravel/telescope",
+ "version": "v5.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/telescope.git",
+ "reference": "ae5c28ca1e40a7a66bfc9b2557e7e1d84d95363c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/telescope/zipball/ae5c28ca1e40a7a66bfc9b2557e7e1d84d95363c",
+ "reference": "ae5c28ca1e40a7a66bfc9b2557e7e1d84d95363c",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "laravel/framework": "^8.37|^9.0|^10.0|^11.0",
+ "php": "^8.0",
+ "symfony/console": "^5.3|^6.0|^7.0",
+ "symfony/var-dumper": "^5.0|^6.0|^7.0"
+ },
+ "require-dev": {
+ "ext-gd": "*",
+ "guzzlehttp/guzzle": "^6.0|^7.0",
+ "laravel/octane": "^1.4|^2.0|dev-develop",
+ "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.0|^10.5"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Laravel\\Telescope\\TelescopeServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Laravel\\Telescope\\": "src/",
+ "Laravel\\Telescope\\Database\\Factories\\": "database/factories/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Taylor Otwell",
+ "email": "taylor@laravel.com"
+ },
+ {
+ "name": "Mohamed Said",
+ "email": "mohamed@laravel.com"
+ }
+ ],
+ "description": "An elegant debug assistant for the Laravel framework.",
+ "keywords": [
+ "debugging",
+ "laravel",
+ "monitoring"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/telescope/issues",
+ "source": "https://github.com/laravel/telescope/tree/v5.0.5"
+ },
+ "time": "2024-05-09T17:09:01+00:00"
+ },
{
"name": "mockery/mockery",
"version": "1.6.12",
@@ -12087,16 +12599,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.11.1",
+ "version": "1.11.3",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b"
+ "reference": "e64220a05c1209fc856d58e789c3b7a32c0bb9a5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e524358f930e41a2b4cca1320e3b04fc26b39e0b",
- "reference": "e524358f930e41a2b4cca1320e3b04fc26b39e0b",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e64220a05c1209fc856d58e789c3b7a32c0bb9a5",
+ "reference": "e64220a05c1209fc856d58e789c3b7a32c0bb9a5",
"shasum": ""
},
"require": {
@@ -12141,7 +12653,7 @@
"type": "github"
}
],
- "time": "2024-05-15T08:00:59+00:00"
+ "time": "2024-05-31T13:53:37+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -13483,16 +13995,16 @@
},
{
"name": "symfony/yaml",
- "version": "v7.0.7",
+ "version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c"
+ "reference": "c5f718c94e3c37dd77b77484e6cf0b524b2d405e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c",
- "reference": "0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/c5f718c94e3c37dd77b77484e6cf0b524b2d405e",
+ "reference": "c5f718c94e3c37dd77b77484e6cf0b524b2d405e",
"shasum": ""
},
"require": {
@@ -13534,7 +14046,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/yaml/tree/v7.0.7"
+ "source": "https://github.com/symfony/yaml/tree/v7.1.0"
},
"funding": [
{
@@ -13550,7 +14062,7 @@
"type": "tidelift"
}
],
- "time": "2024-04-28T11:44:19+00:00"
+ "time": "2024-04-28T18:29:00+00:00"
},
{
"name": "theseer/tokenizer",
diff --git a/config/websockets.php b/config/websockets.php
deleted file mode 100644
index 359d69da..00000000
--- a/config/websockets.php
+++ /dev/null
@@ -1,143 +0,0 @@
- [
- 'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001),
- ],
-
- /*
- * This package comes with multi tenancy out of the box. Here you can
- * configure the different apps that can use the webSockets server.
- *
- * Optionally you specify capacity so you can limit the maximum
- * concurrent connections for a specific app.
- *
- * Optionally you can disable client events so clients cannot send
- * messages to each other via the webSockets.
- */
- 'apps' => [
- [
- 'id' => env('PUSHER_APP_ID'),
- 'name' => env('APP_NAME'),
- 'key' => env('PUSHER_APP_KEY'),
- 'secret' => env('PUSHER_APP_SECRET'),
- 'path' => env('PUSHER_APP_PATH'),
- 'capacity' => null,
- 'enable_client_messages' => false,
- 'enable_statistics' => true,
- ],
- ],
-
- /*
- * This class is responsible for finding the apps. The default provider
- * will use the apps defined in this config file.
- *
- * You can create a custom provider by implementing the
- * `AppProvider` interface.
- */
- 'app_provider' => BeyondCode\LaravelWebSockets\Apps\ConfigAppProvider::class,
-
- /*
- * This array contains the hosts of which you want to allow incoming requests.
- * Leave this empty if you want to accept requests from all hosts.
- */
- 'allowed_origins' => [
- //
- ],
-
- /*
- * The maximum request size in kilobytes that is allowed for an incoming WebSocket request.
- */
- 'max_request_size_in_kb' => 250,
-
- /*
- * This path will be used to register the necessary routes for the package.
- */
- 'path' => 'laravel-websockets',
-
- /*
- * Dashboard Routes Middleware
- *
- * These middleware will be assigned to every dashboard route, giving you
- * the chance to add your own middleware to this list or change any of
- * the existing middleware. Or, you can simply stick with this list.
- */
- 'middleware' => [
- 'web',
- Authorize::class,
- ],
-
- 'statistics' => [
- /*
- * This model will be used to store the statistics of the WebSocketsServer.
- * The only requirement is that the model should extend
- * `WebSocketsStatisticsEntry` provided by this package.
- */
- 'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
-
- /**
- * The Statistics Logger will, by default, handle the incoming statistics, store them
- * and then release them into the database on each interval defined below.
- */
- 'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class,
-
- /*
- * Here you can specify the interval in seconds at which statistics should be logged.
- */
- 'interval_in_seconds' => 60,
-
- /*
- * When the clean-command is executed, all recorded statistics older than
- * the number of days specified here will be deleted.
- */
- 'delete_statistics_older_than_days' => 60,
-
- /*
- * Use an DNS resolver to make the requests to the statistics logger
- * default is to resolve everything to 127.0.0.1.
- */
- 'perform_dns_lookup' => false,
- ],
-
- /*
- * Define the optional SSL context for your WebSocket connections.
- * You can see all available options at: http://php.net/manual/en/context.ssl.php
- */
- 'ssl' => [
- /*
- * Path to local certificate file on filesystem. It must be a PEM encoded file which
- * contains your certificate and private key. It can optionally contain the
- * certificate chain of issuers. The private key also may be contained
- * in a separate file specified by local_pk.
- */
- 'local_cert' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT', null),
-
- /*
- * Path to local private key file on filesystem in case of separate files for
- * certificate (local_cert) and private key.
- */
- 'local_pk' => env('LARAVEL_WEBSOCKETS_SSL_LOCAL_PK', null),
-
- /*
- * Passphrase for your local_cert file.
- */
- 'passphrase' => env('LARAVEL_WEBSOCKETS_SSL_PASSPHRASE', null),
- ],
-
- /*
- * Channel Manager
- * This class handles how channel persistence is handled.
- * By default, persistence is stored in an array by the running webserver.
- * The only requirement is that the class should implement
- * `ChannelManager` interface provided by this package.
- */
- 'channel_manager' => \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManagers\ArrayChannelManager::class,
-];
diff --git a/database/migrations/2024_06_02_212434_create_pulse_tables.php b/database/migrations/2024_06_02_212434_create_pulse_tables.php
new file mode 100644
index 00000000..5d194e2c
--- /dev/null
+++ b/database/migrations/2024_06_02_212434_create_pulse_tables.php
@@ -0,0 +1,84 @@
+shouldRun()) {
+ return;
+ }
+
+ Schema::create('pulse_values', function (Blueprint $table) {
+ $table->id();
+ $table->unsignedInteger('timestamp');
+ $table->string('type');
+ $table->mediumText('key');
+ match ($this->driver()) {
+ 'mariadb', 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'),
+ 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'),
+ 'sqlite' => $table->string('key_hash'),
+ };
+ $table->mediumText('value');
+
+ $table->index('timestamp'); // For trimming...
+ $table->index('type'); // For fast lookups and purging...
+ $table->unique(['type', 'key_hash']); // For data integrity and upserts...
+ });
+
+ Schema::create('pulse_entries', function (Blueprint $table) {
+ $table->id();
+ $table->unsignedInteger('timestamp');
+ $table->string('type');
+ $table->mediumText('key');
+ match ($this->driver()) {
+ 'mariadb', 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'),
+ 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'),
+ 'sqlite' => $table->string('key_hash'),
+ };
+ $table->bigInteger('value')->nullable();
+
+ $table->index('timestamp'); // For trimming...
+ $table->index('type'); // For purging...
+ $table->index('key_hash'); // For mapping...
+ $table->index(['timestamp', 'type', 'key_hash', 'value']); // For aggregate queries...
+ });
+
+ Schema::create('pulse_aggregates', function (Blueprint $table) {
+ $table->id();
+ $table->unsignedInteger('bucket');
+ $table->unsignedMediumInteger('period');
+ $table->string('type');
+ $table->mediumText('key');
+ match ($this->driver()) {
+ 'mariadb', 'mysql' => $table->char('key_hash', 16)->charset('binary')->virtualAs('unhex(md5(`key`))'),
+ 'pgsql' => $table->uuid('key_hash')->storedAs('md5("key")::uuid'),
+ 'sqlite' => $table->string('key_hash'),
+ };
+ $table->string('aggregate');
+ $table->decimal('value', 20, 2);
+ $table->unsignedInteger('count')->nullable();
+
+ $table->unique(['bucket', 'period', 'type', 'aggregate', 'key_hash']); // Force "on duplicate update"...
+ $table->index(['period', 'bucket']); // For trimming...
+ $table->index('type'); // For purging...
+ $table->index(['period', 'type', 'aggregate', 'bucket']); // For aggregate queries...
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('pulse_values');
+ Schema::dropIfExists('pulse_entries');
+ Schema::dropIfExists('pulse_aggregates');
+ }
+};
diff --git a/database/migrations/2024_06_02_213101_create_telescope_entries_table.php b/database/migrations/2024_06_02_213101_create_telescope_entries_table.php
new file mode 100644
index 00000000..700a83f0
--- /dev/null
+++ b/database/migrations/2024_06_02_213101_create_telescope_entries_table.php
@@ -0,0 +1,70 @@
+getConnection());
+
+ $schema->create('telescope_entries', function (Blueprint $table) {
+ $table->bigIncrements('sequence');
+ $table->uuid('uuid');
+ $table->uuid('batch_id');
+ $table->string('family_hash')->nullable();
+ $table->boolean('should_display_on_index')->default(true);
+ $table->string('type', 20);
+ $table->longText('content');
+ $table->dateTime('created_at')->nullable();
+
+ $table->unique('uuid');
+ $table->index('batch_id');
+ $table->index('family_hash');
+ $table->index('created_at');
+ $table->index(['type', 'should_display_on_index']);
+ });
+
+ $schema->create('telescope_entries_tags', function (Blueprint $table) {
+ $table->uuid('entry_uuid');
+ $table->string('tag');
+
+ $table->primary(['entry_uuid', 'tag']);
+ $table->index('tag');
+
+ $table->foreign('entry_uuid')
+ ->references('uuid')
+ ->on('telescope_entries')
+ ->onDelete('cascade');
+ });
+
+ $schema->create('telescope_monitoring', function (Blueprint $table) {
+ $table->string('tag')->primary();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ $schema = Schema::connection($this->getConnection());
+
+ $schema->dropIfExists('telescope_entries_tags');
+ $schema->dropIfExists('telescope_entries');
+ $schema->dropIfExists('telescope_monitoring');
+ }
+};
diff --git a/docker/websocket/supervisord.conf b/docker/websocket/supervisord.conf
index 416a3b1b..3467d026 100644
--- a/docker/websocket/supervisord.conf
+++ b/docker/websocket/supervisord.conf
@@ -1,11 +1,11 @@
[supervisord]
nodaemon=true
user=root
-logfile=/var/log/supervisor/supervisord.log
+logfile=/var/www/html/storage/logs/websocket.log
pidfile=/var/run/supervisord.pid
[program:websockets]
-command=/usr/bin/php /var/www/html/artisan reverb:start --port=6001
+command=/usr/bin/php /var/www/html/artisan reverb:start --debug --port=6001
numprocs=1
autostart=true
autorestart=true
diff --git a/resources/js/Components/ContextMenus/ContextMenu.vue b/resources/js/Components/ContextMenus/ContextMenu.vue
index 8aa96a49..6e0e4366 100644
--- a/resources/js/Components/ContextMenus/ContextMenu.vue
+++ b/resources/js/Components/ContextMenus/ContextMenu.vue
@@ -1,13 +1,10 @@
- {{ header }}
{{ body }}
- {{ footer }}
+
+
+
+
diff --git a/resources/js/Components/Spork/Atoms/MetricCard.vue b/resources/js/Components/Spork/Atoms/MetricCard.vue
index 35830923..f5a50873 100644
--- a/resources/js/Components/Spork/Atoms/MetricCard.vue
+++ b/resources/js/Components/Spork/Atoms/MetricCard.vue
@@ -1,9 +1,10 @@
@@ -15,6 +16,9 @@ const { title, value, loading } = defineProps({
+
+
{{ value }}
+
+ {{subTitle}}
+
+
-
+
-
-
-
+
+
{{ selectedItems.length }} selected
@@ -61,7 +67,12 @@
-
+
|