diff --git a/.lando.dist.yml b/.lando.dist.yml
index 736c72f..049fa0b 100644
--- a/.lando.dist.yml
+++ b/.lando.dist.yml
@@ -1,12 +1,30 @@
-#file: noinspection ComposeUnknownKeys
-name: eclipse-world
+#file: noinspection ComposeUnknownKeys,YAMLSchemaValidation
+name: eclipse-world-plugin
+recipe: laravel
+config:
+ webroot: workbench/public
+ php: '8.3'
+ via: nginx
+ database: mariadb:10.11
services:
appserver:
type: php:custom
xdebug: "debug,develop,coverage"
- via: cli
+ environment:
+ TZ: "Europe/Ljubljana"
+ APP_BASE_PATH: "/app/workbench"
+ TESTBENCH_WORKING_PATH: "/app"
overrides:
- image: slimdeluxe/php:8.2-v1.1
+ image: slimdeluxe/php:8.3-v1.3
+ platform: linux/amd64
+ run:
+ - composer install --no-interaction --prefer-dist
+ - composer run setup --no-interaction
+ - composer run build --no-interaction
+ appserver_nginx:
+ scanner:
+ path: /admin/login
+ retry: 5
tooling:
php:
service: appserver
diff --git a/README.md b/README.md
index d955857..0134e2f 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,25 @@ Should you want to contribute, please see the development guidelines in the [Dat
````
4. You can now develop and run tests. Happy coding 😉
+#### Workbench + Lando (browser testing)
+
+This package ships with a minimal Testbench Workbench so you can run the Filament UI without a separate app:
+
+1. Clone the repository
+2. Start the container
+ ```shell
+ lando start
+ ```
+
+3. Open the admin panel at `https://eclipse-world-plugin.lndo.site/admin`
+
+**No login required** - you'll be automatically signed in as a test user with full permissions.
+
+Notes:
+- The container serves `workbench/public` as the webroot.
+- Use `lando test` for `package:test` and `lando testbench` for other Testbench commands.
+- No Telescope, websockets or health checks are enabled to keep the setup minimal.
+
💡 To manually test the plugin in the browser, see our [recommendation](https://github.com/DataLinx/eclipsephp-core/blob/main/docs/Documentation.md#-plugin-development), which is also [how Filament suggests package development](https://filamentphp.com/docs/3.x/support/contributing#developing-with-a-local-copy-of-filament).
However, the plugin should be universal and not dependent on our app setup or core package.
diff --git a/composer.json b/composer.json
index f047f36..66eea59 100644
--- a/composer.json
+++ b/composer.json
@@ -72,9 +72,11 @@
"@php vendor/bin/testbench serve --ansi"
],
"setup": [
+ "@php -r \"if (!file_exists('workbench/.env')) { copy('workbench/.env.example', 'workbench/.env'); echo '.env file created from .env.example\\n'; }\"",
+ "@php vendor/bin/testbench key:generate --ansi",
"npm install",
- "@php vendor/bin/testbench vendor:publish --provider='Spatie\\Permission\\PermissionServiceProvider'",
"@php vendor/bin/testbench vendor:publish --tag='filament-shield-config'",
+ "@php vendor/bin/testbench filament:assets",
"@php vendor/bin/testbench package:sync-skeleton"
]
},
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index ee48e7b..2405929 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -19,7 +19,7 @@
-
+
diff --git a/testbench.yaml b/testbench.yaml
index 64a584a..2b8d0ef 100644
--- a/testbench.yaml
+++ b/testbench.yaml
@@ -1,13 +1,21 @@
laravel: '@testbench'
+env:
+ - DB_CONNECTION=sqlite
+ - DB_DATABASE=/app/workbench/database/database.sqlite
+ - APP_KEY=base64:ZQvPGC7uVADkjOgtGIIuCI8u3/Pzu+VaRObIbHsgjCc=
+ - APP_ENV=local
+ - APP_DEBUG=true
+ - SESSION_DRIVER=database
+ - CACHE_STORE=database
+ - QUEUE_CONNECTION=sync
+
providers:
- Workbench\App\Providers\WorkbenchServiceProvider
migrations:
- workbench/database/migrations
-
-seeders:
- - Workbench\Database\Seeders\DatabaseSeeder
+ - database/migrations
workbench:
start: '/'
@@ -16,7 +24,7 @@ workbench:
discovers:
web: true
api: false
- commands: false
+ commands: true
components: false
views: false
build:
@@ -26,7 +34,3 @@ workbench:
- migrate-fresh
assets:
- laravel-assets
- sync:
- - from: storage
- to: workbench/storage
- reverse: true
diff --git a/workbench/.env.example b/workbench/.env.example
index e5488ab..589f315 100644
--- a/workbench/.env.example
+++ b/workbench/.env.example
@@ -1,8 +1,8 @@
APP_NAME=Laravel
APP_ENV=local
-APP_KEY=AckfSECXIvnK5r28GVIWUAxmbBSjTsmF
+APP_KEY=
APP_DEBUG=true
-APP_URL=http://localhost
+APP_URL=https://eclipse-world-plugin.lndo.site
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
@@ -21,23 +21,26 @@ LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
+DB_DATABASE=/app/workbench/database/database.sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
-# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
-SESSION_DRIVER=cookie
+SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
-SESSION_DOMAIN=null
+SESSION_DOMAIN=.eclipse-world-plugin.lndo.site
+SESSION_SECURE_COOKIE=true
+SESSION_HTTP_ONLY=true
+SESSION_SAME_SITE=lax
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
-QUEUE_CONNECTION=database
+QUEUE_CONNECTION=sync
-CACHE_STORE=database
+CACHE_STORE=array
# CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
diff --git a/workbench/.gitignore b/workbench/.gitignore
index 3badc3a..4f2455e 100644
--- a/workbench/.gitignore
+++ b/workbench/.gitignore
@@ -1,3 +1,23 @@
.env
.env.dusk
-storage
+storage/app/*
+!storage/app/.gitkeep
+!storage/app/public/
+storage/app/public/*
+!storage/app/public/.gitkeep
+storage/framework/sessions/*
+!storage/framework/sessions/.gitkeep
+storage/framework/testing/*
+!storage/framework/testing/.gitkeep
+storage/framework/views/*
+!storage/framework/views/.gitkeep
+storage/logs/*
+!storage/logs/.gitkeep
+stubs/
+resources/views/vendor/
+lang/
+vendor
+public/build
+public/hot
+/public/css
+/public/js
diff --git a/workbench/app/Http/Middleware/WorkbenchBootstrap.php b/workbench/app/Http/Middleware/WorkbenchBootstrap.php
new file mode 100644
index 0000000..adddb77
--- /dev/null
+++ b/workbench/app/Http/Middleware/WorkbenchBootstrap.php
@@ -0,0 +1,179 @@
+check()) {
+ $user = User::query()->first();
+
+ if (! $user) {
+ try {
+ $user = User::query()->firstOrCreate(
+ ['email' => 'test@example.com'],
+ [
+ 'name' => 'Admin User',
+ 'password' => Hash::make('password'),
+ 'email_verified_at' => now(),
+ ],
+ );
+ } catch (\Throwable $e) {
+ Log::error('[Workbench] User creation failed', ['message' => $e->getMessage()]);
+ // In case of a race/unique constraint, fetch the existing one
+ $user = User::query()->where('email', 'test@example.com')->first();
+ }
+ }
+
+ if ($user) {
+ $this->bootstrapPermissionsAndAssign($user);
+ Auth::guard('web')->login($user);
+ $request->session()->regenerate();
+
+ if ($request->is('admin/login')) {
+ return redirect()->to('/admin');
+ }
+ }
+ }
+
+ return $next($request);
+ }
+
+ private function bootstrapPermissionsAndAssign(User $user): void
+ {
+ // Use cache to prevent running this multiple times
+ $cacheKey = 'workbench:permissions:bootstrapped';
+
+ if (Cache::has($cacheKey)) {
+ // Just ensure user has roles if already bootstrapped
+ $this->ensureUserHasRoles($user);
+
+ return;
+ }
+
+ try {
+ // Use lock to prevent concurrent execution
+ Cache::lock('workbench:bootstrap-permissions', 30)->block(10, function () use ($user, $cacheKey) {
+ // Double-check inside the lock
+ if (Cache::has($cacheKey)) {
+ return;
+ }
+
+ // Normalize guards first
+ DB::table('permissions')->whereNull('guard_name')->orWhere('guard_name', '')->update(['guard_name' => 'web']);
+ DB::table('roles')->whereNull('guard_name')->orWhere('guard_name', '')->update(['guard_name' => 'web']);
+
+ // Generate Filament Shield permissions if none exist yet
+ if (Permission::query()->count() === 0) {
+ Artisan::call('shield:generate', [
+ '--all' => true,
+ '--panel' => 'admin',
+ ]);
+ }
+
+ // Reset caches/registrar to ensure guards are picked up
+ Artisan::call('permission:cache-reset');
+ app(PermissionRegistrar::class)->forgetCachedPermissions();
+
+ // Ensure roles with correct guard
+ $this->ensureRolesHaveCorrectGuard();
+
+ // Create roles
+ $superAdmin = Role::firstOrCreate(['name' => 'super_admin', 'guard_name' => 'web']);
+ $panelUser = Role::firstOrCreate(['name' => 'panel_user', 'guard_name' => 'web']);
+
+ // Only assign permissions if the role doesn't already have them
+ $this->assignPermissionsToRole($superAdmin);
+
+ // Assign roles to user
+ $this->ensureUserHasRoles($user);
+
+ // Mark as bootstrapped (cache for 1 hour)
+ Cache::put($cacheKey, true, 3600);
+ });
+ } catch (\Throwable $e) {
+ Log::error('[Workbench] Bootstrap permissions failed', ['message' => $e->getMessage()]);
+ }
+ }
+
+ private function ensureRolesHaveCorrectGuard(): void
+ {
+ $existingSuper = Role::where('name', 'super_admin')->first();
+ if ($existingSuper && $existingSuper->guard_name !== 'web') {
+ $existingSuper->guard_name = 'web';
+ $existingSuper->save();
+ }
+
+ $existingPanel = Role::where('name', 'panel_user')->first();
+ if ($existingPanel && $existingPanel->guard_name !== 'web') {
+ $existingPanel->guard_name = 'web';
+ $existingPanel->save();
+ }
+ }
+
+ private function assignPermissionsToRole(Role $role): void
+ {
+ // Check if role already has permissions to avoid duplicate inserts
+ if ($role->permissions()->count() > 0) {
+ return;
+ }
+
+ $permissions = Permission::query()->where('guard_name', 'web')->get();
+ if ($permissions->isNotEmpty()) {
+ // Use DB transaction to ensure atomicity
+ DB::transaction(function () use ($role, $permissions) {
+ // Clear existing permissions first to avoid duplicates
+ $role->permissions()->detach();
+
+ // Batch insert to avoid individual constraint violations
+ $pivotData = $permissions->map(function ($permission) use ($role) {
+ return [
+ 'role_id' => $role->id,
+ 'permission_id' => $permission->id,
+ ];
+ })->toArray();
+
+ // Use insert ignore equivalent for SQLite
+ foreach ($pivotData as $data) {
+ DB::table('role_has_permissions')
+ ->insertOrIgnore($data);
+ }
+ });
+ }
+ }
+
+ private function ensureUserHasRoles(User $user): void
+ {
+ $superAdmin = Role::where('name', 'super_admin')->where('guard_name', 'web')->first();
+ $panelUser = Role::where('name', 'panel_user')->where('guard_name', 'web')->first();
+
+ $rolesToAssign = collect([$superAdmin, $panelUser])
+ ->filter()
+ ->pluck('name')
+ ->toArray();
+
+ if (! empty($rolesToAssign)) {
+ // Only sync if user doesn't already have these roles
+ $existingRoles = $user->roles()->pluck('name')->toArray();
+ $missingRoles = array_diff($rolesToAssign, $existingRoles);
+
+ if (! empty($missingRoles)) {
+ $user->assignRole($missingRoles);
+ }
+ }
+ }
+}
diff --git a/workbench/app/Policies/RolePolicy.php b/workbench/app/Policies/RolePolicy.php
new file mode 100644
index 0000000..ad2a069
--- /dev/null
+++ b/workbench/app/Policies/RolePolicy.php
@@ -0,0 +1,108 @@
+can('view_any_role');
+ }
+
+ /**
+ * Determine whether the user can view the model.
+ */
+ public function view(Authorizable $user, Role $role): bool
+ {
+ return $user->can('view_role');
+ }
+
+ /**
+ * Determine whether the user can create models.
+ */
+ public function create(Authorizable $user): bool
+ {
+ return $user->can('create_role');
+ }
+
+ /**
+ * Determine whether the user can update the model.
+ */
+ public function update(Authorizable $user, Role $role): bool
+ {
+ return $user->can('update_role');
+ }
+
+ /**
+ * Determine whether the user can delete the model.
+ */
+ public function delete(Authorizable $user, Role $role): bool
+ {
+ return $user->can('delete_role');
+ }
+
+ /**
+ * Determine whether the user can bulk delete.
+ */
+ public function deleteAny(Authorizable $user): bool
+ {
+ return $user->can('delete_any_role');
+ }
+
+ /**
+ * Determine whether the user can permanently delete.
+ */
+ public function forceDelete(Authorizable $user, Role $role): bool
+ {
+ return $user->can('force_delete_role');
+ }
+
+ /**
+ * Determine whether the user can permanently bulk delete.
+ */
+ public function forceDeleteAny(Authorizable $user): bool
+ {
+ return $user->can('force_delete_any_role');
+ }
+
+ /**
+ * Determine whether the user can restore.
+ */
+ public function restore(Authorizable $user, Role $role): bool
+ {
+ return $user->can('restore_role');
+ }
+
+ /**
+ * Determine whether the user can bulk restore.
+ */
+ public function restoreAny(Authorizable $user): bool
+ {
+ return $user->can('restore_any_role');
+ }
+
+ /**
+ * Determine whether the user can replicate.
+ */
+ public function replicate(Authorizable $user, Role $role): bool
+ {
+ return $user->can('replicate_role');
+ }
+
+ /**
+ * Determine whether the user can reorder.
+ */
+ public function reorder(Authorizable $user): bool
+ {
+ return $user->can('reorder_role');
+ }
+}
diff --git a/workbench/app/Providers/AdminPanelProvider.php b/workbench/app/Providers/AdminPanelProvider.php
index 538c5f7..53d4427 100644
--- a/workbench/app/Providers/AdminPanelProvider.php
+++ b/workbench/app/Providers/AdminPanelProvider.php
@@ -10,15 +10,14 @@
use Filament\Pages\Dashboard;
use Filament\Panel;
use Filament\PanelProvider;
-use Filament\Support\Facades\FilamentView;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Session\Middleware\AuthenticateSession;
use Illuminate\Session\Middleware\StartSession;
-use Illuminate\Support\Facades\Blade;
use Illuminate\View\Middleware\ShareErrorsFromSession;
+use Workbench\App\Http\Middleware\WorkbenchBootstrap;
class AdminPanelProvider extends PanelProvider
{
@@ -39,6 +38,7 @@ public function panel(Panel $panel): Panel
SubstituteBindings::class,
DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class,
+ WorkbenchBootstrap::class,
])
->authMiddleware([
Authenticate::class,
@@ -47,6 +47,7 @@ public function panel(Panel $panel): Panel
FilamentShieldPlugin::make(),
EclipseWorld::make(),
])
+ ->viteTheme(false)
->pages([
Dashboard::class,
]);
@@ -55,7 +56,5 @@ public function panel(Panel $panel): Panel
public function register(): void
{
parent::register();
-
- FilamentView::registerRenderHook('panels::body.end', fn (): string => Blade::render("@vite('resources/js/app.js')"));
}
}
diff --git a/workbench/app/Providers/AuthServiceProvider.php b/workbench/app/Providers/AuthServiceProvider.php
new file mode 100644
index 0000000..0d0599d
--- /dev/null
+++ b/workbench/app/Providers/AuthServiceProvider.php
@@ -0,0 +1,27 @@
+
+ */
+ protected $policies = [
+ Role::class => RolePolicy::class,
+ ];
+
+ /**
+ * Register any authentication / authorization services.
+ */
+ public function boot(): void
+ {
+ $this->registerPolicies();
+ }
+}
diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php
index 5c21824..bd60efb 100644
--- a/workbench/app/Providers/WorkbenchServiceProvider.php
+++ b/workbench/app/Providers/WorkbenchServiceProvider.php
@@ -11,7 +11,12 @@ class WorkbenchServiceProvider extends ServiceProvider
*/
public function register(): void
{
+ $this->app->register(\Spatie\Permission\PermissionServiceProvider::class);
+ $this->app->register(\BezhanSalleh\FilamentShield\FilamentShieldServiceProvider::class);
+ $this->app->register(\Livewire\LivewireServiceProvider::class);
+ $this->app->register(\Filament\FilamentServiceProvider::class);
$this->app->register(AdminPanelProvider::class);
+ $this->app->register(AuthServiceProvider::class);
}
/**
diff --git a/workbench/bootstrap/app.php b/workbench/bootstrap/app.php
index 6ead72a..3fa4760 100644
--- a/workbench/bootstrap/app.php
+++ b/workbench/bootstrap/app.php
@@ -3,10 +3,12 @@
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
+use Workbench\App\Providers\WorkbenchServiceProvider;
-use function Orchestra\Testbench\default_skeleton_path;
-
-return Application::configure(basePath: $APP_BASE_PATH ?? default_skeleton_path())
+return Application::configure(basePath: $APP_BASE_PATH ?? dirname(__DIR__))
+ ->withProviders([
+ WorkbenchServiceProvider::class,
+ ])
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
diff --git a/workbench/bootstrap/cache/.gitignore b/workbench/bootstrap/cache/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/workbench/bootstrap/cache/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/workbench/composer.json b/workbench/composer.json
new file mode 100644
index 0000000..f1779e0
--- /dev/null
+++ b/workbench/composer.json
@@ -0,0 +1,11 @@
+{
+ "name": "workbench/app",
+ "type": "project",
+ "autoload": {
+ "psr-4": {
+ "Workbench\\App\\": "app/"
+ }
+ }
+}
+
+
diff --git a/workbench/config/app.php b/workbench/config/app.php
new file mode 100644
index 0000000..f467267
--- /dev/null
+++ b/workbench/config/app.php
@@ -0,0 +1,126 @@
+ env('APP_NAME', 'Laravel'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Environment
+ |--------------------------------------------------------------------------
+ |
+ | This value determines the "environment" your application is currently
+ | running in. This may determine how you prefer to configure various
+ | services the application utilizes. Set this in your ".env" file.
+ |
+ */
+
+ 'env' => env('APP_ENV', 'production'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Debug Mode
+ |--------------------------------------------------------------------------
+ |
+ | When your application is in debug mode, detailed error messages with
+ | stack traces will be shown on every error that occurs within your
+ | application. If disabled, a simple generic error page is shown.
+ |
+ */
+
+ 'debug' => (bool) env('APP_DEBUG', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application URL
+ |--------------------------------------------------------------------------
+ |
+ | This URL is used by the console to properly generate URLs when using
+ | the Artisan command line tool. You should set this to the root of
+ | the application so that it's available within Artisan commands.
+ |
+ */
+
+ 'url' => env('APP_URL', 'http://localhost'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Timezone
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the default timezone for your application, which
+ | will be used by the PHP date and date-time functions. The timezone
+ | is set to "UTC" by default as it is suitable for most use cases.
+ |
+ */
+
+ 'timezone' => env('APP_TIMEZONE', 'UTC'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Locale Configuration
+ |--------------------------------------------------------------------------
+ |
+ | The application locale determines the default locale that will be used
+ | by Laravel's translation / localization methods. This option can be
+ | set to any locale for which you plan to have translation strings.
+ |
+ */
+
+ 'locale' => env('APP_LOCALE', 'en'),
+
+ 'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
+
+ 'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Encryption Key
+ |--------------------------------------------------------------------------
+ |
+ | This key is utilized by Laravel's encryption services and should be set
+ | to a random, 32 character string to ensure that all encrypted values
+ | are secure. You should do this prior to deploying the application.
+ |
+ */
+
+ 'cipher' => 'AES-256-CBC',
+
+ 'key' => env('APP_KEY'),
+
+ 'previous_keys' => [
+ ...array_filter(
+ explode(',', env('APP_PREVIOUS_KEYS', ''))
+ ),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Maintenance Mode Driver
+ |--------------------------------------------------------------------------
+ |
+ | These configuration options determine the driver used to determine and
+ | manage Laravel's "maintenance mode" status. The "cache" driver will
+ | allow maintenance mode to be controlled across multiple machines.
+ |
+ | Supported drivers: "file", "cache"
+ |
+ */
+
+ 'maintenance' => [
+ 'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
+ 'store' => env('APP_MAINTENANCE_STORE', 'database'),
+ ],
+
+];
diff --git a/workbench/config/auth.php b/workbench/config/auth.php
new file mode 100644
index 0000000..8337867
--- /dev/null
+++ b/workbench/config/auth.php
@@ -0,0 +1,115 @@
+ [
+ 'guard' => env('AUTH_GUARD', 'web'),
+ 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Authentication Guards
+ |--------------------------------------------------------------------------
+ |
+ | Next, you may define every authentication guard for your application.
+ | Of course, a great default configuration has been defined for you
+ | which utilizes session storage plus the Eloquent user provider.
+ |
+ | All authentication guards have a user provider, which defines how the
+ | users are actually retrieved out of your database or other storage
+ | system used by the application. Typically, Eloquent is utilized.
+ |
+ | Supported: "session"
+ |
+ */
+
+ 'guards' => [
+ 'web' => [
+ 'driver' => 'session',
+ 'provider' => 'users',
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | User Providers
+ |--------------------------------------------------------------------------
+ |
+ | All authentication guards have a user provider, which defines how the
+ | users are actually retrieved out of your database or other storage
+ | system used by the application. Typically, Eloquent is utilized.
+ |
+ | If you have multiple user tables or models you may configure multiple
+ | providers to represent the model / table. These providers may then
+ | be assigned to any extra authentication guards you have defined.
+ |
+ | Supported: "database", "eloquent"
+ |
+ */
+
+ 'providers' => [
+ 'users' => [
+ 'driver' => 'eloquent',
+ 'model' => env('AUTH_MODEL', \Workbench\App\Models\User::class),
+ ],
+
+ // 'users' => [
+ // 'driver' => 'database',
+ // 'table' => 'users',
+ // ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Resetting Passwords
+ |--------------------------------------------------------------------------
+ |
+ | These configuration options specify the behavior of Laravel's password
+ | reset functionality, including the table utilized for token storage
+ | and the user provider that is invoked to actually retrieve users.
+ |
+ | The expiry time is the number of minutes that each reset token will be
+ | considered valid. This security feature keeps tokens short-lived so
+ | they have less time to be guessed. You may change this as needed.
+ |
+ | The throttle setting is the number of seconds a user must wait before
+ | generating more password reset tokens. This prevents the user from
+ | quickly generating a very large amount of password reset tokens.
+ |
+ */
+
+ 'passwords' => [
+ 'users' => [
+ 'provider' => 'users',
+ 'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
+ 'expire' => 60,
+ 'throttle' => 60,
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Password Confirmation Timeout
+ |--------------------------------------------------------------------------
+ |
+ | Here you may define the amount of seconds before a password confirmation
+ | window expires and users are asked to re-enter their password via the
+ | confirmation screen. By default, the timeout lasts for three hours.
+ |
+ */
+
+ 'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
+
+];
diff --git a/workbench/config/blade-heroicons.php b/workbench/config/blade-heroicons.php
new file mode 100644
index 0000000..e517a97
--- /dev/null
+++ b/workbench/config/blade-heroicons.php
@@ -0,0 +1,57 @@
+ 'heroicon',
+
+ /*
+ |-----------------------------------------------------------------
+ | Fallback Icon
+ |-----------------------------------------------------------------
+ |
+ | This config option allows you to define a fallback
+ | icon when an icon in this set cannot be found.
+ |
+ */
+
+ 'fallback' => '',
+
+ /*
+ |-----------------------------------------------------------------
+ | Default Set Classes
+ |-----------------------------------------------------------------
+ |
+ | This config option allows you to define some classes which
+ | will be applied by default to all icons within this set.
+ |
+ */
+
+ 'class' => '',
+
+ /*
+ |-----------------------------------------------------------------
+ | Default Set Attributes
+ |-----------------------------------------------------------------
+ |
+ | This config option allows you to define some attributes which
+ | will be applied by default to all icons within this set.
+ |
+ */
+
+ 'attributes' => [
+ // 'width' => 50,
+ // 'height' => 50,
+ ],
+
+];
diff --git a/workbench/config/blade-icons.php b/workbench/config/blade-icons.php
new file mode 100644
index 0000000..5aade2a
--- /dev/null
+++ b/workbench/config/blade-icons.php
@@ -0,0 +1,183 @@
+ [
+
+ // 'default' => [
+ //
+ // /*
+ // |-----------------------------------------------------------------
+ // | Icons Path
+ // |-----------------------------------------------------------------
+ // |
+ // | Provide the relative path from your app root to your SVG icons
+ // | directory. Icons are loaded recursively so there's no need to
+ // | list every sub-directory.
+ // |
+ // | Relative to the disk root when the disk option is set.
+ // |
+ // */
+ //
+ // 'path' => 'resources/svg',
+ //
+ // /*
+ // |-----------------------------------------------------------------
+ // | Filesystem Disk
+ // |-----------------------------------------------------------------
+ // |
+ // | Optionally, provide a specific filesystem disk to read
+ // | icons from. When defining a disk, the "path" option
+ // | starts relatively from the disk root.
+ // |
+ // */
+ //
+ // 'disk' => '',
+ //
+ // /*
+ // |-----------------------------------------------------------------
+ // | Default Prefix
+ // |-----------------------------------------------------------------
+ // |
+ // | This config option allows you to define a default prefix for
+ // | your icons. The dash separator will be applied automatically
+ // | to every icon name. It's required and needs to be unique.
+ // |
+ // */
+ //
+ // 'prefix' => 'icon',
+ //
+ // /*
+ // |-----------------------------------------------------------------
+ // | Fallback Icon
+ // |-----------------------------------------------------------------
+ // |
+ // | This config option allows you to define a fallback
+ // | icon when an icon in this set cannot be found.
+ // |
+ // */
+ //
+ // 'fallback' => '',
+ //
+ // /*
+ // |-----------------------------------------------------------------
+ // | Default Set Classes
+ // |-----------------------------------------------------------------
+ // |
+ // | This config option allows you to define some classes which
+ // | will be applied by default to all icons within this set.
+ // |
+ // */
+ //
+ // 'class' => '',
+ //
+ // /*
+ // |-----------------------------------------------------------------
+ // | Default Set Attributes
+ // |-----------------------------------------------------------------
+ // |
+ // | This config option allows you to define some attributes which
+ // | will be applied by default to all icons within this set.
+ // |
+ // */
+ //
+ // 'attributes' => [
+ // // 'width' => 50,
+ // // 'height' => 50,
+ // ],
+ //
+ // ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Global Default Classes
+ |--------------------------------------------------------------------------
+ |
+ | This config option allows you to define some classes which
+ | will be applied by default to all icons.
+ |
+ */
+
+ 'class' => '',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Global Default Attributes
+ |--------------------------------------------------------------------------
+ |
+ | This config option allows you to define some attributes which
+ | will be applied by default to all icons.
+ |
+ */
+
+ 'attributes' => [
+ // 'width' => 50,
+ // 'height' => 50,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Global Fallback Icon
+ |--------------------------------------------------------------------------
+ |
+ | This config option allows you to define a global fallback
+ | icon when an icon in any set cannot be found. It can
+ | reference any icon from any configured set.
+ |
+ */
+
+ 'fallback' => '',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Components
+ |--------------------------------------------------------------------------
+ |
+ | These config options allow you to define some
+ | settings related to Blade Components.
+ |
+ */
+
+ 'components' => [
+
+ /*
+ |----------------------------------------------------------------------
+ | Disable Components
+ |----------------------------------------------------------------------
+ |
+ | This config option allows you to disable Blade components
+ | completely. It's useful to avoid performance problems
+ | when working with large icon libraries.
+ |
+ */
+
+ 'disabled' => false,
+
+ /*
+ |----------------------------------------------------------------------
+ | Default Icon Component Name
+ |----------------------------------------------------------------------
+ |
+ | This config option allows you to define the name
+ | for the default Icon class component.
+ |
+ */
+
+ 'default' => 'icon',
+
+ ],
+
+];
diff --git a/workbench/config/cache.php b/workbench/config/cache.php
new file mode 100644
index 0000000..4319e97
--- /dev/null
+++ b/workbench/config/cache.php
@@ -0,0 +1,108 @@
+ env('CACHE_STORE', 'array'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Cache Stores
+ |--------------------------------------------------------------------------
+ |
+ | Here you may define all of the cache "stores" for your application as
+ | well as their drivers. You may even define multiple stores for the
+ | same cache driver to group types of items stored in your caches.
+ |
+ | Supported drivers: "array", "database", "file", "memcached",
+ | "redis", "dynamodb", "octane", "null"
+ |
+ */
+
+ 'stores' => [
+
+ 'array' => [
+ 'driver' => 'array',
+ 'serialize' => false,
+ ],
+
+ 'database' => [
+ 'driver' => 'database',
+ 'connection' => env('DB_CACHE_CONNECTION'),
+ 'table' => env('DB_CACHE_TABLE', 'cache'),
+ 'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
+ 'lock_table' => env('DB_CACHE_LOCK_TABLE'),
+ ],
+
+ 'file' => [
+ 'driver' => 'file',
+ 'path' => storage_path('framework/cache/data'),
+ 'lock_path' => storage_path('framework/cache/data'),
+ ],
+
+ 'memcached' => [
+ 'driver' => 'memcached',
+ 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
+ 'sasl' => [
+ env('MEMCACHED_USERNAME'),
+ env('MEMCACHED_PASSWORD'),
+ ],
+ 'options' => [
+ // Memcached::OPT_CONNECT_TIMEOUT => 2000,
+ ],
+ 'servers' => [
+ [
+ 'host' => env('MEMCACHED_HOST', '127.0.0.1'),
+ 'port' => env('MEMCACHED_PORT', 11211),
+ 'weight' => 100,
+ ],
+ ],
+ ],
+
+ 'redis' => [
+ 'driver' => 'redis',
+ 'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
+ 'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
+ ],
+
+ 'dynamodb' => [
+ 'driver' => 'dynamodb',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
+ 'endpoint' => env('DYNAMODB_ENDPOINT'),
+ ],
+
+ 'octane' => [
+ 'driver' => 'octane',
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Cache Key Prefix
+ |--------------------------------------------------------------------------
+ |
+ | When utilizing the APC, database, memcached, Redis, and DynamoDB cache
+ | stores, there might be other applications using the same cache. For
+ | that reason, you may prefix every cache key to avoid collisions.
+ |
+ */
+
+ 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),
+
+];
diff --git a/workbench/config/concurrency.php b/workbench/config/concurrency.php
new file mode 100644
index 0000000..cb8022b
--- /dev/null
+++ b/workbench/config/concurrency.php
@@ -0,0 +1,20 @@
+ env('CONCURRENCY_DRIVER', 'process'),
+
+];
diff --git a/workbench/config/cors.php b/workbench/config/cors.php
new file mode 100644
index 0000000..8a39e6d
--- /dev/null
+++ b/workbench/config/cors.php
@@ -0,0 +1,34 @@
+ ['api/*', 'sanctum/csrf-cookie'],
+
+ 'allowed_methods' => ['*'],
+
+ 'allowed_origins' => ['*'],
+
+ 'allowed_origins_patterns' => [],
+
+ 'allowed_headers' => ['*'],
+
+ 'exposed_headers' => [],
+
+ 'max_age' => 0,
+
+ 'supports_credentials' => false,
+
+];
diff --git a/workbench/config/database.php b/workbench/config/database.php
new file mode 100644
index 0000000..125949e
--- /dev/null
+++ b/workbench/config/database.php
@@ -0,0 +1,173 @@
+ env('DB_CONNECTION', 'sqlite'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Database Connections
+ |--------------------------------------------------------------------------
+ |
+ | Below are all of the database connections defined for your application.
+ | An example configuration is provided for each database system which
+ | is supported by Laravel. You're free to add / remove connections.
+ |
+ */
+
+ 'connections' => [
+
+ 'sqlite' => [
+ 'driver' => 'sqlite',
+ 'url' => env('DB_URL'),
+ 'database' => env('DB_DATABASE', database_path('database.sqlite')),
+ 'prefix' => '',
+ 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
+ 'busy_timeout' => null,
+ 'journal_mode' => null,
+ 'synchronous' => null,
+ ],
+
+ 'mysql' => [
+ 'driver' => 'mysql',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', '127.0.0.1'),
+ 'port' => env('DB_PORT', '3306'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'unix_socket' => env('DB_SOCKET', ''),
+ 'charset' => env('DB_CHARSET', 'utf8mb4'),
+ 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'strict' => true,
+ 'engine' => null,
+ 'options' => extension_loaded('pdo_mysql') ? array_filter([
+ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
+ ]) : [],
+ ],
+
+ 'mariadb' => [
+ 'driver' => 'mariadb',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', '127.0.0.1'),
+ 'port' => env('DB_PORT', '3306'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'unix_socket' => env('DB_SOCKET', ''),
+ 'charset' => env('DB_CHARSET', 'utf8mb4'),
+ 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'strict' => true,
+ 'engine' => null,
+ 'options' => extension_loaded('pdo_mysql') ? array_filter([
+ PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
+ ]) : [],
+ ],
+
+ 'pgsql' => [
+ 'driver' => 'pgsql',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', '127.0.0.1'),
+ 'port' => env('DB_PORT', '5432'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'charset' => env('DB_CHARSET', 'utf8'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ 'search_path' => 'public',
+ 'sslmode' => 'prefer',
+ ],
+
+ 'sqlsrv' => [
+ 'driver' => 'sqlsrv',
+ 'url' => env('DB_URL'),
+ 'host' => env('DB_HOST', 'localhost'),
+ 'port' => env('DB_PORT', '1433'),
+ 'database' => env('DB_DATABASE', 'laravel'),
+ 'username' => env('DB_USERNAME', 'root'),
+ 'password' => env('DB_PASSWORD', ''),
+ 'charset' => env('DB_CHARSET', 'utf8'),
+ 'prefix' => '',
+ 'prefix_indexes' => true,
+ // 'encrypt' => env('DB_ENCRYPT', 'yes'),
+ // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Migration Repository Table
+ |--------------------------------------------------------------------------
+ |
+ | This table keeps track of all the migrations that have already run for
+ | your application. Using this information, we can determine which of
+ | the migrations on disk haven't actually been run on the database.
+ |
+ */
+
+ 'migrations' => [
+ 'table' => 'migrations',
+ 'update_date_on_publish' => true,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Redis Databases
+ |--------------------------------------------------------------------------
+ |
+ | Redis is an open source, fast, and advanced key-value store that also
+ | provides a richer body of commands than a typical key-value system
+ | such as Memcached. You may define your connection settings here.
+ |
+ */
+
+ 'redis' => [
+
+ 'client' => env('REDIS_CLIENT', 'phpredis'),
+
+ 'options' => [
+ 'cluster' => env('REDIS_CLUSTER', 'redis'),
+ 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
+ ],
+
+ 'default' => [
+ 'url' => env('REDIS_URL'),
+ 'host' => env('REDIS_HOST', '127.0.0.1'),
+ 'username' => env('REDIS_USERNAME'),
+ 'password' => env('REDIS_PASSWORD'),
+ 'port' => env('REDIS_PORT', '6379'),
+ 'database' => env('REDIS_DB', '0'),
+ ],
+
+ 'cache' => [
+ 'url' => env('REDIS_URL'),
+ 'host' => env('REDIS_HOST', '127.0.0.1'),
+ 'username' => env('REDIS_USERNAME'),
+ 'password' => env('REDIS_PASSWORD'),
+ 'port' => env('REDIS_PORT', '6379'),
+ 'database' => env('REDIS_CACHE_DB', '1'),
+ ],
+
+ ],
+
+];
diff --git a/workbench/config/eclipse-world.php b/workbench/config/eclipse-world.php
new file mode 100644
index 0000000..3ac44ad
--- /dev/null
+++ b/workbench/config/eclipse-world.php
@@ -0,0 +1,5 @@
+ [
+ 'should_register_navigation' => true,
+ 'slug' => 'shield/roles',
+ 'navigation_sort' => -1,
+ 'navigation_badge' => true,
+ 'navigation_group' => true,
+ 'sub_navigation_position' => null,
+ 'is_globally_searchable' => false,
+ 'show_model_path' => true,
+ 'is_scoped_to_tenant' => true,
+ 'cluster' => null,
+ ],
+
+ 'tenant_model' => null,
+
+ 'auth_provider_model' => [
+ 'fqcn' => 'Workbench\\App\\Models\\User',
+ ],
+
+ 'super_admin' => [
+ 'enabled' => true,
+ 'name' => 'super_admin',
+ 'define_via_gate' => false,
+ 'intercept_gate' => 'before', // after
+ ],
+
+ 'panel_user' => [
+ 'enabled' => true,
+ 'name' => 'panel_user',
+ ],
+
+ 'permission_prefixes' => [
+ 'resource' => [
+ 'view',
+ 'view_any',
+ 'create',
+ 'update',
+ 'restore',
+ 'restore_any',
+ 'replicate',
+ 'reorder',
+ 'delete',
+ 'delete_any',
+ 'force_delete',
+ 'force_delete_any',
+ ],
+
+ 'page' => 'page',
+ 'widget' => 'widget',
+ ],
+
+ 'entities' => [
+ 'pages' => true,
+ 'widgets' => true,
+ 'resources' => true,
+ 'custom_permissions' => false,
+ ],
+
+ 'generator' => [
+ 'option' => 'permissions',
+ 'policy_directory' => 'Policies',
+ 'policy_namespace' => 'Policies',
+ ],
+
+ 'exclude' => [
+ 'enabled' => true,
+
+ 'pages' => [
+ 'Dashboard',
+ ],
+
+ 'widgets' => [
+ 'AccountWidget', 'FilamentInfoWidget',
+ ],
+
+ 'resources' => [],
+ ],
+
+ 'discovery' => [
+ 'discover_all_resources' => false,
+ 'discover_all_widgets' => false,
+ 'discover_all_pages' => false,
+ ],
+
+ 'register_role_policy' => [
+ 'enabled' => true,
+ ],
+
+];
diff --git a/workbench/config/filament.php b/workbench/config/filament.php
new file mode 100644
index 0000000..488a01f
--- /dev/null
+++ b/workbench/config/filament.php
@@ -0,0 +1,101 @@
+ [
+
+ // 'echo' => [
+ // 'broadcaster' => 'pusher',
+ // 'key' => env('VITE_PUSHER_APP_KEY'),
+ // 'cluster' => env('VITE_PUSHER_APP_CLUSTER'),
+ // 'wsHost' => env('VITE_PUSHER_HOST'),
+ // 'wsPort' => env('VITE_PUSHER_PORT'),
+ // 'wssPort' => env('VITE_PUSHER_PORT'),
+ // 'authEndpoint' => '/broadcasting/auth',
+ // 'disableStats' => true,
+ // 'encrypted' => true,
+ // 'forceTLS' => true,
+ // ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default Filesystem Disk
+ |--------------------------------------------------------------------------
+ |
+ | This is the storage disk Filament will use to store files. You may use
+ | any of the disks defined in the `config/filesystems.php`.
+ |
+ */
+
+ 'default_filesystem_disk' => env('FILAMENT_FILESYSTEM_DISK', 'public'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Assets Path
+ |--------------------------------------------------------------------------
+ |
+ | This is the directory where Filament's assets will be published to. It
+ | is relative to the `public` directory of your Laravel application.
+ |
+ | After changing the path, you should run `php artisan filament:assets`.
+ |
+ */
+
+ 'assets_path' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Cache Path
+ |--------------------------------------------------------------------------
+ |
+ | This is the directory that Filament will use to store cache files that
+ | are used to optimize the registration of components.
+ |
+ | After changing the path, you should run `php artisan filament:cache-components`.
+ |
+ */
+
+ 'cache_path' => base_path('bootstrap/cache/filament'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Livewire Loading Delay
+ |--------------------------------------------------------------------------
+ |
+ | This sets the delay before loading indicators appear.
+ |
+ | Setting this to 'none' makes indicators appear immediately, which can be
+ | desirable for high-latency connections. Setting it to 'default' applies
+ | Livewire's standard 200ms delay.
+ |
+ */
+
+ 'livewire_loading_delay' => 'default',
+
+ /*
+ |--------------------------------------------------------------------------
+ | System Route Prefix
+ |--------------------------------------------------------------------------
+ |
+ | This is the prefix used for the system routes that Filament registers,
+ | such as the routes for downloading exports and failed import rows.
+ |
+ */
+
+ 'system_route_prefix' => 'filament',
+
+];
diff --git a/workbench/config/filesystems.php b/workbench/config/filesystems.php
new file mode 100644
index 0000000..3d671bd
--- /dev/null
+++ b/workbench/config/filesystems.php
@@ -0,0 +1,80 @@
+ env('FILESYSTEM_DISK', 'local'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Filesystem Disks
+ |--------------------------------------------------------------------------
+ |
+ | Below you may configure as many filesystem disks as necessary, and you
+ | may even configure multiple disks for the same driver. Examples for
+ | most supported storage drivers are configured here for reference.
+ |
+ | Supported drivers: "local", "ftp", "sftp", "s3"
+ |
+ */
+
+ 'disks' => [
+
+ 'local' => [
+ 'driver' => 'local',
+ 'root' => storage_path('app/private'),
+ 'serve' => true,
+ 'throw' => false,
+ 'report' => false,
+ ],
+
+ 'public' => [
+ 'driver' => 'local',
+ 'root' => storage_path('app/public'),
+ 'url' => env('APP_URL').'/storage',
+ 'visibility' => 'public',
+ 'throw' => false,
+ 'report' => false,
+ ],
+
+ 's3' => [
+ 'driver' => 's3',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'region' => env('AWS_DEFAULT_REGION'),
+ 'bucket' => env('AWS_BUCKET'),
+ 'url' => env('AWS_URL'),
+ 'endpoint' => env('AWS_ENDPOINT'),
+ 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
+ 'throw' => false,
+ 'report' => false,
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Symbolic Links
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the symbolic links that will be created when the
+ | `storage:link` Artisan command is executed. The array keys should be
+ | the locations of the links and the values should be their targets.
+ |
+ */
+
+ 'links' => [
+ public_path('storage') => storage_path('app/public'),
+ ],
+
+];
diff --git a/workbench/config/hashing.php b/workbench/config/hashing.php
new file mode 100644
index 0000000..9eb408e
--- /dev/null
+++ b/workbench/config/hashing.php
@@ -0,0 +1,67 @@
+ env('HASH_DRIVER', 'bcrypt'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Bcrypt Options
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the configuration options that should be used when
+ | passwords are hashed using the Bcrypt algorithm. This will allow you
+ | to control the amount of time it takes to hash the given password.
+ |
+ */
+
+ 'bcrypt' => [
+ 'rounds' => env('BCRYPT_ROUNDS', 12),
+ 'verify' => env('HASH_VERIFY', true),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Argon Options
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the configuration options that should be used when
+ | passwords are hashed using the Argon algorithm. These will allow you
+ | to control the amount of time it takes to hash the given password.
+ |
+ */
+
+ 'argon' => [
+ 'memory' => env('ARGON_MEMORY', 65536),
+ 'threads' => env('ARGON_THREADS', 1),
+ 'time' => env('ARGON_TIME', 4),
+ 'verify' => env('HASH_VERIFY', true),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Rehash On Login
+ |--------------------------------------------------------------------------
+ |
+ | Setting this option to true will tell Laravel to automatically rehash
+ | the user's password during login if the configured work factor for
+ | the algorithm has changed, allowing graceful upgrades of hashes.
+ |
+ */
+
+ 'rehash_on_login' => true,
+
+];
diff --git a/workbench/config/livewire.php b/workbench/config/livewire.php
new file mode 100644
index 0000000..0d2ba89
--- /dev/null
+++ b/workbench/config/livewire.php
@@ -0,0 +1,160 @@
+ 'App\\Livewire',
+
+ /*
+ |---------------------------------------------------------------------------
+ | View Path
+ |---------------------------------------------------------------------------
+ |
+ | This value is used to specify where Livewire component Blade templates are
+ | stored when running file creation commands like `artisan make:livewire`.
+ | It is also used if you choose to omit a component's render() method.
+ |
+ */
+
+ 'view_path' => resource_path('views/livewire'),
+
+ /*
+ |---------------------------------------------------------------------------
+ | Layout
+ |---------------------------------------------------------------------------
+ | The view that will be used as the layout when rendering a single component
+ | as an entire page via `Route::get('/post/create', CreatePost::class);`.
+ | In this case, the view returned by CreatePost will render into $slot.
+ |
+ */
+
+ 'layout' => 'components.layouts.app',
+
+ /*
+ |---------------------------------------------------------------------------
+ | Lazy Loading Placeholder
+ |---------------------------------------------------------------------------
+ | Livewire allows you to lazy load components that would otherwise slow down
+ | the initial page load. Every component can have a custom placeholder or
+ | you can define the default placeholder view for all components below.
+ |
+ */
+
+ 'lazy_placeholder' => null,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Temporary File Uploads
+ |---------------------------------------------------------------------------
+ |
+ | Livewire handles file uploads by storing uploads in a temporary directory
+ | before the file is stored permanently. All file uploads are directed to
+ | a global endpoint for temporary storage. You may configure this below:
+ |
+ */
+
+ 'temporary_file_upload' => [
+ 'disk' => null, // Example: 'local', 's3' | Default: 'default'
+ 'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB)
+ 'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp'
+ 'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1'
+ 'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs...
+ 'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
+ 'mov', 'avi', 'wmv', 'mp3', 'm4a',
+ 'jpg', 'jpeg', 'mpga', 'webp', 'wma',
+ ],
+ 'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated...
+ 'cleanup' => true, // Should cleanup temporary uploads older than 24 hrs...
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | Render On Redirect
+ |---------------------------------------------------------------------------
+ |
+ | This value determines if Livewire will run a component's `render()` method
+ | after a redirect has been triggered using something like `redirect(...)`
+ | Setting this to true will render the view once more before redirecting
+ |
+ */
+
+ 'render_on_redirect' => false,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Eloquent Model Binding
+ |---------------------------------------------------------------------------
+ |
+ | Previous versions of Livewire supported binding directly to eloquent model
+ | properties using wire:model by default. However, this behavior has been
+ | deemed too "magical" and has therefore been put under a feature flag.
+ |
+ */
+
+ 'legacy_model_binding' => false,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Auto-inject Frontend Assets
+ |---------------------------------------------------------------------------
+ |
+ | By default, Livewire automatically injects its JavaScript and CSS into the
+ |
and of pages containing Livewire components. By disabling
+ | this behavior, you need to use @livewireStyles and @livewireScripts.
+ |
+ */
+
+ 'inject_assets' => true,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Navigate (SPA mode)
+ |---------------------------------------------------------------------------
+ |
+ | By adding `wire:navigate` to links in your Livewire application, Livewire
+ | will prevent the default link handling and instead request those pages
+ | via AJAX, creating an SPA-like effect. Configure this behavior here.
+ |
+ */
+
+ 'navigate' => [
+ 'show_progress_bar' => true,
+ 'progress_bar_color' => '#2299dd',
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | HTML Morph Markers
+ |---------------------------------------------------------------------------
+ |
+ | Livewire intelligently "morphs" existing HTML into the newly rendered HTML
+ | after each update. To make this process more reliable, Livewire injects
+ | "markers" into the rendered Blade surrounding @if, @class & @foreach.
+ |
+ */
+
+ 'inject_morph_markers' => true,
+
+ /*
+ |---------------------------------------------------------------------------
+ | Pagination Theme
+ |---------------------------------------------------------------------------
+ |
+ | When enabling Livewire's pagination feature by using the `WithPagination`
+ | trait, Livewire will use Tailwind templates to render pagination views
+ | on the page. If you want Bootstrap CSS, you can specify: "bootstrap"
+ |
+ */
+
+ 'pagination_theme' => 'tailwind',
+];
diff --git a/workbench/config/logging.php b/workbench/config/logging.php
new file mode 100644
index 0000000..8d94292
--- /dev/null
+++ b/workbench/config/logging.php
@@ -0,0 +1,132 @@
+ env('LOG_CHANNEL', 'stack'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Deprecations Log Channel
+ |--------------------------------------------------------------------------
+ |
+ | This option controls the log channel that should be used to log warnings
+ | regarding deprecated PHP and library features. This allows you to get
+ | your application ready for upcoming major versions of dependencies.
+ |
+ */
+
+ 'deprecations' => [
+ 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
+ 'trace' => env('LOG_DEPRECATIONS_TRACE', false),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Log Channels
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the log channels for your application. Laravel
+ | utilizes the Monolog PHP logging library, which includes a variety
+ | of powerful log handlers and formatters that you're free to use.
+ |
+ | Available drivers: "single", "daily", "slack", "syslog",
+ | "errorlog", "monolog", "custom", "stack"
+ |
+ */
+
+ 'channels' => [
+
+ 'stack' => [
+ 'driver' => 'stack',
+ 'channels' => explode(',', env('LOG_STACK', 'single')),
+ 'ignore_exceptions' => false,
+ ],
+
+ 'single' => [
+ 'driver' => 'single',
+ 'path' => storage_path('logs/laravel.log'),
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'replace_placeholders' => true,
+ ],
+
+ 'daily' => [
+ 'driver' => 'daily',
+ 'path' => storage_path('logs/laravel.log'),
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'days' => env('LOG_DAILY_DAYS', 14),
+ 'replace_placeholders' => true,
+ ],
+
+ 'slack' => [
+ 'driver' => 'slack',
+ 'url' => env('LOG_SLACK_WEBHOOK_URL'),
+ 'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
+ 'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
+ 'level' => env('LOG_LEVEL', 'critical'),
+ 'replace_placeholders' => true,
+ ],
+
+ 'papertrail' => [
+ 'driver' => 'monolog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
+ 'handler_with' => [
+ 'host' => env('PAPERTRAIL_URL'),
+ 'port' => env('PAPERTRAIL_PORT'),
+ 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
+ ],
+ 'processors' => [PsrLogMessageProcessor::class],
+ ],
+
+ 'stderr' => [
+ 'driver' => 'monolog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'handler' => StreamHandler::class,
+ 'formatter' => env('LOG_STDERR_FORMATTER'),
+ 'with' => [
+ 'stream' => 'php://stderr',
+ ],
+ 'processors' => [PsrLogMessageProcessor::class],
+ ],
+
+ 'syslog' => [
+ 'driver' => 'syslog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
+ 'replace_placeholders' => true,
+ ],
+
+ 'errorlog' => [
+ 'driver' => 'errorlog',
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'replace_placeholders' => true,
+ ],
+
+ 'null' => [
+ 'driver' => 'monolog',
+ 'handler' => NullHandler::class,
+ ],
+
+ 'emergency' => [
+ 'path' => storage_path('logs/laravel.log'),
+ ],
+
+ ],
+
+];
diff --git a/workbench/config/permission.php b/workbench/config/permission.php
new file mode 100644
index 0000000..f39f6b5
--- /dev/null
+++ b/workbench/config/permission.php
@@ -0,0 +1,202 @@
+ [
+
+ /*
+ * When using the "HasPermissions" trait from this package, we need to know which
+ * Eloquent model should be used to retrieve your permissions. Of course, it
+ * is often just the "Permission" model but you may use whatever you like.
+ *
+ * The model you want to use as a Permission model needs to implement the
+ * `Spatie\Permission\Contracts\Permission` contract.
+ */
+
+ 'permission' => Spatie\Permission\Models\Permission::class,
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * Eloquent model should be used to retrieve your roles. Of course, it
+ * is often just the "Role" model but you may use whatever you like.
+ *
+ * The model you want to use as a Role model needs to implement the
+ * `Spatie\Permission\Contracts\Role` contract.
+ */
+
+ 'role' => Spatie\Permission\Models\Role::class,
+
+ ],
+
+ 'table_names' => [
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * table should be used to retrieve your roles. We have chosen a basic
+ * default value but you may easily change it to any table you like.
+ */
+
+ 'roles' => 'roles',
+
+ /*
+ * When using the "HasPermissions" trait from this package, we need to know which
+ * table should be used to retrieve your permissions. We have chosen a basic
+ * default value but you may easily change it to any table you like.
+ */
+
+ 'permissions' => 'permissions',
+
+ /*
+ * When using the "HasPermissions" trait from this package, we need to know which
+ * table should be used to retrieve your models permissions. We have chosen a
+ * basic default value but you may easily change it to any table you like.
+ */
+
+ 'model_has_permissions' => 'model_has_permissions',
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * table should be used to retrieve your models roles. We have chosen a
+ * basic default value but you may easily change it to any table you like.
+ */
+
+ 'model_has_roles' => 'model_has_roles',
+
+ /*
+ * When using the "HasRoles" trait from this package, we need to know which
+ * table should be used to retrieve your roles permissions. We have chosen a
+ * basic default value but you may easily change it to any table you like.
+ */
+
+ 'role_has_permissions' => 'role_has_permissions',
+ ],
+
+ 'column_names' => [
+ /*
+ * Change this if you want to name the related pivots other than defaults
+ */
+ 'role_pivot_key' => null, // default 'role_id',
+ 'permission_pivot_key' => null, // default 'permission_id',
+
+ /*
+ * Change this if you want to name the related model primary key other than
+ * `model_id`.
+ *
+ * For example, this would be nice if your primary keys are all UUIDs. In
+ * that case, name this `model_uuid`.
+ */
+
+ 'model_morph_key' => 'model_id',
+
+ /*
+ * Change this if you want to use the teams feature and your related model's
+ * foreign key is other than `team_id`.
+ */
+
+ 'team_foreign_key' => 'team_id',
+ ],
+
+ /*
+ * When set to true, the method for checking permissions will be registered on the gate.
+ * Set this to false if you want to implement custom logic for checking permissions.
+ */
+
+ 'register_permission_check_method' => true,
+
+ /*
+ * When set to true, Laravel\Octane\Events\OperationTerminated event listener will be registered
+ * this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated
+ * NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it.
+ */
+ 'register_octane_reset_listener' => false,
+
+ /*
+ * Events will fire when a role or permission is assigned/unassigned:
+ * \Spatie\Permission\Events\RoleAttached
+ * \Spatie\Permission\Events\RoleDetached
+ * \Spatie\Permission\Events\PermissionAttached
+ * \Spatie\Permission\Events\PermissionDetached
+ *
+ * To enable, set to true, and then create listeners to watch these events.
+ */
+ 'events_enabled' => false,
+
+ /*
+ * Teams Feature.
+ * When set to true the package implements teams using the 'team_foreign_key'.
+ * If you want the migrations to register the 'team_foreign_key', you must
+ * set this to true before doing the migration.
+ * If you already did the migration then you must make a new migration to also
+ * add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions'
+ * (view the latest version of this package's migration file)
+ */
+
+ 'teams' => false,
+
+ /*
+ * The class to use to resolve the permissions team id
+ */
+ 'team_resolver' => \Spatie\Permission\DefaultTeamResolver::class,
+
+ /*
+ * Passport Client Credentials Grant
+ * When set to true the package will use Passports Client to check permissions
+ */
+
+ 'use_passport_client_credentials' => false,
+
+ /*
+ * When set to true, the required permission names are added to exception messages.
+ * This could be considered an information leak in some contexts, so the default
+ * setting is false here for optimum safety.
+ */
+
+ 'display_permission_in_exception' => false,
+
+ /*
+ * When set to true, the required role names are added to exception messages.
+ * This could be considered an information leak in some contexts, so the default
+ * setting is false here for optimum safety.
+ */
+
+ 'display_role_in_exception' => false,
+
+ /*
+ * By default wildcard permission lookups are disabled.
+ * See documentation to understand supported syntax.
+ */
+
+ 'enable_wildcard_permission' => false,
+
+ /*
+ * The class to use for interpreting wildcard permissions.
+ * If you need to modify delimiters, override the class and specify its name here.
+ */
+ // 'wildcard_permission' => Spatie\Permission\WildcardPermission::class,
+
+ /* Cache-specific settings */
+
+ 'cache' => [
+
+ /*
+ * By default all permissions are cached for 24 hours to speed up performance.
+ * When permissions or roles are updated the cache is flushed automatically.
+ */
+
+ 'expiration_time' => \DateInterval::createFromDateString('24 hours'),
+
+ /*
+ * The cache key used to store all permissions.
+ */
+
+ 'key' => 'spatie.permission.cache',
+
+ /*
+ * You may optionally indicate a specific cache driver to use for permission and
+ * role caching using any of the `store` drivers listed in the cache.php config
+ * file. Using 'default' here means to use the `default` set in cache.php.
+ */
+
+ 'store' => 'default',
+ ],
+];
diff --git a/workbench/config/queue.php b/workbench/config/queue.php
new file mode 100644
index 0000000..116bd8d
--- /dev/null
+++ b/workbench/config/queue.php
@@ -0,0 +1,112 @@
+ env('QUEUE_CONNECTION', 'database'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Queue Connections
+ |--------------------------------------------------------------------------
+ |
+ | Here you may configure the connection options for every queue backend
+ | used by your application. An example configuration is provided for
+ | each backend supported by Laravel. You're also free to add more.
+ |
+ | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
+ |
+ */
+
+ 'connections' => [
+
+ 'sync' => [
+ 'driver' => 'sync',
+ ],
+
+ 'database' => [
+ 'driver' => 'database',
+ 'connection' => env('DB_QUEUE_CONNECTION'),
+ 'table' => env('DB_QUEUE_TABLE', 'jobs'),
+ 'queue' => env('DB_QUEUE', 'default'),
+ 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
+ 'after_commit' => false,
+ ],
+
+ 'beanstalkd' => [
+ 'driver' => 'beanstalkd',
+ 'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
+ 'queue' => env('BEANSTALKD_QUEUE', 'default'),
+ 'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
+ 'block_for' => 0,
+ 'after_commit' => false,
+ ],
+
+ 'sqs' => [
+ 'driver' => 'sqs',
+ 'key' => env('AWS_ACCESS_KEY_ID'),
+ 'secret' => env('AWS_SECRET_ACCESS_KEY'),
+ 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
+ 'queue' => env('SQS_QUEUE', 'default'),
+ 'suffix' => env('SQS_SUFFIX'),
+ 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
+ 'after_commit' => false,
+ ],
+
+ 'redis' => [
+ 'driver' => 'redis',
+ 'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
+ 'queue' => env('REDIS_QUEUE', 'default'),
+ 'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
+ 'block_for' => null,
+ 'after_commit' => false,
+ ],
+
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Job Batching
+ |--------------------------------------------------------------------------
+ |
+ | The following options configure the database and table that store job
+ | batching information. These options can be updated to any database
+ | connection and table which has been defined by your application.
+ |
+ */
+
+ 'batching' => [
+ 'database' => env('DB_CONNECTION', 'sqlite'),
+ 'table' => 'job_batches',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Failed Queue Jobs
+ |--------------------------------------------------------------------------
+ |
+ | These options configure the behavior of failed queue job logging so you
+ | can control how and where failed jobs are stored. Laravel ships with
+ | support for storing failed jobs in a simple file or in a database.
+ |
+ | Supported drivers: "database-uuids", "dynamodb", "file", "null"
+ |
+ */
+
+ 'failed' => [
+ 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
+ 'database' => env('DB_CONNECTION', 'sqlite'),
+ 'table' => 'failed_jobs',
+ ],
+
+];
diff --git a/workbench/config/session.php b/workbench/config/session.php
new file mode 100644
index 0000000..ba0aa60
--- /dev/null
+++ b/workbench/config/session.php
@@ -0,0 +1,217 @@
+ env('SESSION_DRIVER', 'database'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Lifetime
+ |--------------------------------------------------------------------------
+ |
+ | Here you may specify the number of minutes that you wish the session
+ | to be allowed to remain idle before it expires. If you want them
+ | to expire immediately when the browser is closed then you may
+ | indicate that via the expire_on_close configuration option.
+ |
+ */
+
+ 'lifetime' => (int) env('SESSION_LIFETIME', 120),
+
+ 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Encryption
+ |--------------------------------------------------------------------------
+ |
+ | This option allows you to easily specify that all of your session data
+ | should be encrypted before it's stored. All encryption is performed
+ | automatically by Laravel and you may use the session like normal.
+ |
+ */
+
+ 'encrypt' => env('SESSION_ENCRYPT', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session File Location
+ |--------------------------------------------------------------------------
+ |
+ | When utilizing the "file" session driver, the session files are placed
+ | on disk. The default storage location is defined here; however, you
+ | are free to provide another location where they should be stored.
+ |
+ */
+
+ 'files' => storage_path('framework/sessions'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Database Connection
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" or "redis" session drivers, you may specify a
+ | connection that should be used to manage these sessions. This should
+ | correspond to a connection in your database configuration options.
+ |
+ */
+
+ 'connection' => env('SESSION_CONNECTION'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Database Table
+ |--------------------------------------------------------------------------
+ |
+ | When using the "database" session driver, you may specify the table to
+ | be used to store sessions. Of course, a sensible default is defined
+ | for you; however, you're welcome to change this to another table.
+ |
+ */
+
+ 'table' => env('SESSION_TABLE', 'sessions'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cache Store
+ |--------------------------------------------------------------------------
+ |
+ | When using one of the framework's cache driven session backends, you may
+ | define the cache store which should be used to store the session data
+ | between requests. This must match one of your defined cache stores.
+ |
+ | Affects: "apc", "dynamodb", "memcached", "redis"
+ |
+ */
+
+ 'store' => env('SESSION_STORE'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Sweeping Lottery
+ |--------------------------------------------------------------------------
+ |
+ | Some session drivers must manually sweep their storage location to get
+ | rid of old sessions from storage. Here are the chances that it will
+ | happen on a given request. By default, the odds are 2 out of 100.
+ |
+ */
+
+ 'lottery' => [2, 100],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Name
+ |--------------------------------------------------------------------------
+ |
+ | Here you may change the name of the session cookie that is created by
+ | the framework. Typically, you should not need to change this value
+ | since doing so does not grant a meaningful security improvement.
+ |
+ */
+
+ 'cookie' => env(
+ 'SESSION_COOKIE',
+ Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
+ ),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Path
+ |--------------------------------------------------------------------------
+ |
+ | The session cookie path determines the path for which the cookie will
+ | be regarded as available. Typically, this will be the root path of
+ | your application, but you're free to change this when necessary.
+ |
+ */
+
+ 'path' => env('SESSION_PATH', '/'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Session Cookie Domain
+ |--------------------------------------------------------------------------
+ |
+ | This value determines the domain and subdomains the session cookie is
+ | available to. By default, the cookie will be available to the root
+ | domain and all subdomains. Typically, this shouldn't be changed.
+ |
+ */
+
+ 'domain' => env('SESSION_DOMAIN'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | HTTPS Only Cookies
+ |--------------------------------------------------------------------------
+ |
+ | By setting this option to true, session cookies will only be sent back
+ | to the server if the browser has a HTTPS connection. This will keep
+ | the cookie from being sent to you when it can't be done securely.
+ |
+ */
+
+ 'secure' => env('SESSION_SECURE_COOKIE'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | HTTP Access Only
+ |--------------------------------------------------------------------------
+ |
+ | Setting this value to true will prevent JavaScript from accessing the
+ | value of the cookie and the cookie will only be accessible through
+ | the HTTP protocol. It's unlikely you should disable this option.
+ |
+ */
+
+ 'http_only' => env('SESSION_HTTP_ONLY', true),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Same-Site Cookies
+ |--------------------------------------------------------------------------
+ |
+ | This option determines how your cookies behave when cross-site requests
+ | take place, and can be used to mitigate CSRF attacks. By default, we
+ | will set this value to "lax" to permit secure cross-site requests.
+ |
+ | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
+ |
+ | Supported: "lax", "strict", "none", null
+ |
+ */
+
+ 'same_site' => env('SESSION_SAME_SITE', 'lax'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Partitioned Cookies
+ |--------------------------------------------------------------------------
+ |
+ | Setting this value to true will tie the cookie to the top-level site for
+ | a cross-site context. Partitioned cookies are accepted by the browser
+ | when flagged "secure" and the Same-Site attribute is set to "none".
+ |
+ */
+
+ 'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
+
+];
diff --git a/workbench/config/tinker.php b/workbench/config/tinker.php
new file mode 100644
index 0000000..c187942
--- /dev/null
+++ b/workbench/config/tinker.php
@@ -0,0 +1,50 @@
+ [
+ // App\Console\Commands\ExampleCommand::class,
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Auto Aliased Classes
+ |--------------------------------------------------------------------------
+ |
+ | Tinker will not automatically alias classes in your vendor namespaces
+ | but you may explicitly allow a subset of classes to get aliased by
+ | adding the names of each of those classes to the following list.
+ |
+ */
+
+ 'alias' => [
+ //
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Classes That Should Not Be Aliased
+ |--------------------------------------------------------------------------
+ |
+ | Typically, Tinker automatically aliases classes as you require them in
+ | Tinker. However, you may wish to never alias certain classes, which
+ | you may accomplish by listing the classes in the following array.
+ |
+ */
+
+ 'dont_alias' => [
+ 'App\Nova',
+ ],
+
+];
diff --git a/workbench/config/view.php b/workbench/config/view.php
new file mode 100644
index 0000000..98dd666
--- /dev/null
+++ b/workbench/config/view.php
@@ -0,0 +1,36 @@
+ [
+ resource_path('views'),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Compiled View Path
+ |--------------------------------------------------------------------------
+ |
+ | This option determines where all the compiled Blade templates will be
+ | stored for your application. Typically, this is within the storage
+ | directory. However, as usual, you are free to change this value.
+ |
+ */
+
+ 'compiled' => env(
+ 'VIEW_COMPILED_PATH',
+ storage_path('framework/views')
+ ),
+
+];
diff --git a/workbench/database/.gitignore b/workbench/database/.gitignore
new file mode 100644
index 0000000..9b19b93
--- /dev/null
+++ b/workbench/database/.gitignore
@@ -0,0 +1 @@
+*.sqlite*
diff --git a/workbench/database/migrations/0001_01_01_000000_testbench_create_users_table.php b/workbench/database/migrations/0001_01_01_000000_testbench_create_users_table.php
new file mode 100644
index 0000000..05fb5d9
--- /dev/null
+++ b/workbench/database/migrations/0001_01_01_000000_testbench_create_users_table.php
@@ -0,0 +1,49 @@
+id();
+ $table->string('name');
+ $table->string('email')->unique();
+ $table->timestamp('email_verified_at')->nullable();
+ $table->string('password');
+ $table->rememberToken();
+ $table->timestamps();
+ });
+
+ Schema::create('password_reset_tokens', function (Blueprint $table) {
+ $table->string('email')->primary();
+ $table->string('token');
+ $table->timestamp('created_at')->nullable();
+ });
+
+ Schema::create('sessions', function (Blueprint $table) {
+ $table->string('id')->primary();
+ $table->foreignId('user_id')->nullable()->index();
+ $table->string('ip_address', 45)->nullable();
+ $table->text('user_agent')->nullable();
+ $table->longText('payload');
+ $table->integer('last_activity')->index();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('users');
+ Schema::dropIfExists('password_reset_tokens');
+ Schema::dropIfExists('sessions');
+ }
+};
diff --git a/workbench/database/migrations/0001_01_01_000001_testbench_create_cache_table.php b/workbench/database/migrations/0001_01_01_000001_testbench_create_cache_table.php
new file mode 100644
index 0000000..b9c106b
--- /dev/null
+++ b/workbench/database/migrations/0001_01_01_000001_testbench_create_cache_table.php
@@ -0,0 +1,35 @@
+string('key')->primary();
+ $table->mediumText('value');
+ $table->integer('expiration');
+ });
+
+ Schema::create('cache_locks', function (Blueprint $table) {
+ $table->string('key')->primary();
+ $table->string('owner');
+ $table->integer('expiration');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('cache');
+ Schema::dropIfExists('cache_locks');
+ }
+};
diff --git a/workbench/database/migrations/0001_01_01_000002_testbench_create_jobs_table.php b/workbench/database/migrations/0001_01_01_000002_testbench_create_jobs_table.php
new file mode 100644
index 0000000..425e705
--- /dev/null
+++ b/workbench/database/migrations/0001_01_01_000002_testbench_create_jobs_table.php
@@ -0,0 +1,57 @@
+id();
+ $table->string('queue')->index();
+ $table->longText('payload');
+ $table->unsignedTinyInteger('attempts');
+ $table->unsignedInteger('reserved_at')->nullable();
+ $table->unsignedInteger('available_at');
+ $table->unsignedInteger('created_at');
+ });
+
+ Schema::create('job_batches', function (Blueprint $table) {
+ $table->string('id')->primary();
+ $table->string('name');
+ $table->integer('total_jobs');
+ $table->integer('pending_jobs');
+ $table->integer('failed_jobs');
+ $table->longText('failed_job_ids');
+ $table->mediumText('options')->nullable();
+ $table->integer('cancelled_at')->nullable();
+ $table->integer('created_at');
+ $table->integer('finished_at')->nullable();
+ });
+
+ Schema::create('failed_jobs', function (Blueprint $table) {
+ $table->id();
+ $table->string('uuid')->unique();
+ $table->text('connection');
+ $table->text('queue');
+ $table->longText('payload');
+ $table->longText('exception');
+ $table->timestamp('failed_at')->useCurrent();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('jobs');
+ Schema::dropIfExists('job_batches');
+ Schema::dropIfExists('failed_jobs');
+ }
+};
diff --git a/workbench/database/migrations/2025_08_10_104332_create_sessions_table.php b/workbench/database/migrations/2025_08_10_104332_create_sessions_table.php
new file mode 100644
index 0000000..ca5922d
--- /dev/null
+++ b/workbench/database/migrations/2025_08_10_104332_create_sessions_table.php
@@ -0,0 +1,33 @@
+string('id')->primary();
+ $table->foreignId('user_id')->nullable()->index();
+ $table->string('ip_address', 45)->nullable();
+ $table->text('user_agent')->nullable();
+ $table->longText('payload');
+ $table->integer('last_activity')->index();
+ });
+ }
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('sessions');
+ }
+};
diff --git a/workbench/database/migrations/2025_08_28_113759_create_notifications_table.php b/workbench/database/migrations/2025_08_28_113759_create_notifications_table.php
new file mode 100644
index 0000000..d738032
--- /dev/null
+++ b/workbench/database/migrations/2025_08_28_113759_create_notifications_table.php
@@ -0,0 +1,31 @@
+uuid('id')->primary();
+ $table->string('type');
+ $table->morphs('notifiable');
+ $table->text('data');
+ $table->timestamp('read_at')->nullable();
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('notifications');
+ }
+};
diff --git a/workbench/database/migrations/2025_08_28_142604_create_permission_tables.php b/workbench/database/migrations/2025_08_28_142604_create_permission_tables.php
new file mode 100644
index 0000000..ce4d9d2
--- /dev/null
+++ b/workbench/database/migrations/2025_08_28_142604_create_permission_tables.php
@@ -0,0 +1,136 @@
+engine('InnoDB');
+ $table->bigIncrements('id'); // permission id
+ $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
+ $table->string('guard_name'); // For MyISAM use string('guard_name', 25);
+ $table->timestamps();
+
+ $table->unique(['name', 'guard_name']);
+ });
+
+ Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) {
+ // $table->engine('InnoDB');
+ $table->bigIncrements('id'); // role id
+ if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
+ $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
+ $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
+ }
+ $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format)
+ $table->string('guard_name'); // For MyISAM use string('guard_name', 25);
+ $table->timestamps();
+ if ($teams || config('permission.testing')) {
+ $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
+ } else {
+ $table->unique(['name', 'guard_name']);
+ }
+ });
+
+ Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
+ $table->unsignedBigInteger($pivotPermission);
+
+ $table->string('model_type');
+ $table->unsignedBigInteger($columnNames['model_morph_key']);
+ $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
+
+ $table->foreign($pivotPermission)
+ ->references('id') // permission id
+ ->on($tableNames['permissions'])
+ ->onDelete('cascade');
+ if ($teams) {
+ $table->unsignedBigInteger($columnNames['team_foreign_key']);
+ $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
+
+ $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_permissions_permission_model_type_primary');
+ } else {
+ $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_permissions_permission_model_type_primary');
+ }
+
+ });
+
+ Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
+ $table->unsignedBigInteger($pivotRole);
+
+ $table->string('model_type');
+ $table->unsignedBigInteger($columnNames['model_morph_key']);
+ $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
+
+ $table->foreign($pivotRole)
+ ->references('id') // role id
+ ->on($tableNames['roles'])
+ ->onDelete('cascade');
+ if ($teams) {
+ $table->unsignedBigInteger($columnNames['team_foreign_key']);
+ $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
+
+ $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_roles_role_model_type_primary');
+ } else {
+ $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
+ 'model_has_roles_role_model_type_primary');
+ }
+ });
+
+ Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
+ $table->unsignedBigInteger($pivotPermission);
+ $table->unsignedBigInteger($pivotRole);
+
+ $table->foreign($pivotPermission)
+ ->references('id') // permission id
+ ->on($tableNames['permissions'])
+ ->onDelete('cascade');
+
+ $table->foreign($pivotRole)
+ ->references('id') // role id
+ ->on($tableNames['roles'])
+ ->onDelete('cascade');
+
+ $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
+ });
+
+ app('cache')
+ ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
+ ->forget(config('permission.cache.key'));
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ $tableNames = config('permission.table_names');
+
+ if (empty($tableNames)) {
+ throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
+ }
+
+ Schema::drop($tableNames['role_has_permissions']);
+ Schema::drop($tableNames['model_has_roles']);
+ Schema::drop($tableNames['model_has_permissions']);
+ Schema::drop($tableNames['roles']);
+ Schema::drop($tableNames['permissions']);
+ }
+};
diff --git a/workbench/database/seeders/DatabaseSeeder.php b/workbench/database/seeders/DatabaseSeeder.php
deleted file mode 100644
index f10adbb..0000000
--- a/workbench/database/seeders/DatabaseSeeder.php
+++ /dev/null
@@ -1,23 +0,0 @@
-times(10)->create();
-
- UserFactory::new()->create([
- 'name' => 'Test User',
- 'email' => 'test@example.com',
- ]);
- }
-}
diff --git a/workbench/public/.htaccess b/workbench/public/.htaccess
new file mode 100644
index 0000000..49cb758
--- /dev/null
+++ b/workbench/public/.htaccess
@@ -0,0 +1,21 @@
+
+
+ Options -MultiViews -Indexes
+
+
+ RewriteEngine On
+
+ # Handle Authorization Header
+ RewriteCond %{HTTP:Authorization} .
+ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+
+ # Redirect Trailing Slashes If Not A Folder...
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_URI} (.+)/$
+ RewriteRule ^ %1 [L,R=301]
+
+ # Send Requests To Front Controller...
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule ^ index.php [L]
+
\ No newline at end of file
diff --git a/workbench/public/index.php b/workbench/public/index.php
new file mode 100644
index 0000000..6d3fffa
--- /dev/null
+++ b/workbench/public/index.php
@@ -0,0 +1,55 @@
+make(Kernel::class);
+
+$response = $kernel->handle(
+ $request = Request::capture()
+)->send();
+
+$kernel->terminate($request, $response);
diff --git a/workbench/public/robots.txt b/workbench/public/robots.txt
new file mode 100644
index 0000000..6f27bb6
--- /dev/null
+++ b/workbench/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow:
\ No newline at end of file
diff --git a/workbench/resources/views/errors/401.blade.php b/workbench/resources/views/errors/401.blade.php
new file mode 100644
index 0000000..5c586db
--- /dev/null
+++ b/workbench/resources/views/errors/401.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Unauthorized'))
+@section('code', '401')
+@section('message', __('Unauthorized'))
diff --git a/workbench/resources/views/errors/402.blade.php b/workbench/resources/views/errors/402.blade.php
new file mode 100644
index 0000000..3bc23ef
--- /dev/null
+++ b/workbench/resources/views/errors/402.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Payment Required'))
+@section('code', '402')
+@section('message', __('Payment Required'))
diff --git a/workbench/resources/views/errors/403.blade.php b/workbench/resources/views/errors/403.blade.php
new file mode 100644
index 0000000..a5506f0
--- /dev/null
+++ b/workbench/resources/views/errors/403.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Forbidden'))
+@section('code', '403')
+@section('message', __($exception->getMessage() ?: 'Forbidden'))
diff --git a/workbench/resources/views/errors/404.blade.php b/workbench/resources/views/errors/404.blade.php
new file mode 100644
index 0000000..7549540
--- /dev/null
+++ b/workbench/resources/views/errors/404.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Not Found'))
+@section('code', '404')
+@section('message', __('Not Found'))
diff --git a/workbench/resources/views/errors/419.blade.php b/workbench/resources/views/errors/419.blade.php
new file mode 100644
index 0000000..c09216e
--- /dev/null
+++ b/workbench/resources/views/errors/419.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Page Expired'))
+@section('code', '419')
+@section('message', __('Page Expired'))
diff --git a/workbench/resources/views/errors/429.blade.php b/workbench/resources/views/errors/429.blade.php
new file mode 100644
index 0000000..f01b07b
--- /dev/null
+++ b/workbench/resources/views/errors/429.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Too Many Requests'))
+@section('code', '429')
+@section('message', __('Too Many Requests'))
diff --git a/workbench/resources/views/errors/500.blade.php b/workbench/resources/views/errors/500.blade.php
new file mode 100644
index 0000000..d9e95d9
--- /dev/null
+++ b/workbench/resources/views/errors/500.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Server Error'))
+@section('code', '500')
+@section('message', __('Server Error'))
diff --git a/workbench/resources/views/errors/503.blade.php b/workbench/resources/views/errors/503.blade.php
new file mode 100644
index 0000000..c5a9dde
--- /dev/null
+++ b/workbench/resources/views/errors/503.blade.php
@@ -0,0 +1,5 @@
+@extends('errors::minimal')
+
+@section('title', __('Service Unavailable'))
+@section('code', '503')
+@section('message', __('Service Unavailable'))
diff --git a/workbench/resources/views/errors/layout.blade.php b/workbench/resources/views/errors/layout.blade.php
new file mode 100644
index 0000000..019c2cd
--- /dev/null
+++ b/workbench/resources/views/errors/layout.blade.php
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+ @yield('title')
+
+
+
+
+
+
+
+
+ @yield('message')
+
+
+
+
+
diff --git a/workbench/resources/views/errors/minimal.blade.php b/workbench/resources/views/errors/minimal.blade.php
new file mode 100644
index 0000000..db69f25
--- /dev/null
+++ b/workbench/resources/views/errors/minimal.blade.php
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+ @yield('title')
+
+
+
+
+
+
+
+
+
+
+ @yield('code')
+
+
+
+ @yield('message')
+
+
+
+
+
+
diff --git a/workbench/resources/views/welcome.blade.php b/workbench/resources/views/welcome.blade.php
new file mode 100644
index 0000000..5c34b66
--- /dev/null
+++ b/workbench/resources/views/welcome.blade.php
@@ -0,0 +1,56 @@
+
+
+
+
+
+ Eclipse World Plugin
+
+
+
+
+
Eclipse World Plugin
+
Welcome to your Laravel workbench environment
+
Access Admin Panel
+
+
+
\ No newline at end of file
diff --git a/workbench/storage/framework/cache/.gitignore b/workbench/storage/framework/cache/.gitignore
new file mode 100644
index 0000000..01e4a6c
--- /dev/null
+++ b/workbench/storage/framework/cache/.gitignore
@@ -0,0 +1,3 @@
+*
+!data/
+!.gitignore
diff --git a/workbench/storage/framework/cache/data/.gitignore b/workbench/storage/framework/cache/data/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/workbench/storage/framework/cache/data/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore