Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`tests/Feature/NamingConventionTest.php`, which reads the live router, `RateLimiter`, Artisan
kernel and middleware-alias map and fails on any bare route name, limiter, command or alias this
package owns.
- `Support\DeprecationNotices`, which announces a deprecated Livewire name or Filament slug once
per process with `E_USER_DEPRECATED`, and `Adapters\Filament\RedirectLegacySlug`, which answers
the page's old URL.
- `RegisteredNames` constants for the view and translation namespaces, the Livewire panel name and
the Filament slug, with their deprecated predecessors.

### Changed

Expand All @@ -22,6 +27,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
namespace, so the bare names were a collision waiting to happen.
- **The API rate limiter is vendor-scoped.** The routes now use `throttle:laranail-env-kit-webui.api`
instead of `throttle:env-kit`. The limit and its bucket key are unchanged.
- The deprecated bare route names are served by `laranail/package-tools`' shared
`BareRouteNameAliases` (declared with `$package->hasDeprecatedRouteNames()`), replacing the
provider's own resolver. Behaviour is unchanged: one logged warning per name, chained to any
resolver registered earlier, never shadowing a host route. The warning now reads "the route name
[...] is deprecated and will stop resolving no earlier than the next minor after 0.1; use
[...]". Requires `laranail/package-tools ^0.1.3`.
- **The Livewire panel is vendor-scoped:** `laranail-env-kit-webui.panel`, which the Filament page
now embeds.
- **The Filament page slug is vendor-scoped:** `laranail-env-kit-webui`, so the page is served at
`{panel}/laranail-env-kit-webui` under the route name
`filament.{panel}.pages.laranail-env-kit-webui`.
- Views and translations are registered under `laranail/env-kit-webui::` as well as
`laranail-env-kit-webui::`, over the same paths. The package's own view calls use the slash
form; its translation calls stay on the hyphen form, which is where a host's overrides in
`lang/vendor/laranail-env-kit-webui/` are read from.
- `NamingConventionTest` runs on package-tools' `AssertsRegisteredNames`, and also covers the
Livewire component, the view and translation namespaces and the Filament slug.

### Deprecated

Expand All @@ -31,6 +53,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
the scoped names there. Earliest removal: the next minor after 0.1.
- The bare `env-kit` rate limiter. It is still registered, delegates to the same limit, and logs a
warning naming `laranail-env-kit-webui.api`. Earliest removal: the next minor after 0.1.
- The Livewire name `env-kit-panel`. It is still registered for the same component; mounting it
raises one `E_USER_DEPRECATED` naming `laranail-env-kit-webui.panel`. Earliest removal: the
next minor after 0.1.
- The Filament page slug `env-kit`. `{panel}/env-kit` redirects to the page, keeping the query
string, under the page's old route name `filament.{panel}.pages.env-kit`, and raises one
`E_USER_DEPRECATED`. Earliest removal: the next minor after 0.1.

### Fixed

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ curl -X PUT -H "Authorization: Bearer $SANCTUM_TOKEN" -H "Accept: application/js
https://acme.test/api/v1/env-kit/keys/MAIL_HOST
```

Route names are `laranail-env-kit-webui.keys.*` and `laranail-env-kit-webui.panel`, the API
limiter is `laranail-env-kit-webui.api`, the Livewire panel is `laranail-env-kit-webui.panel`,
and the Filament page slug is `laranail-env-kit-webui`. The older bare names (`env-kit.*`
routes, the `env-kit` limiter, the `env-kit-panel` component and the `env-kit` page slug) are
deprecated aliases that still work, each announcing its replacement once.

The full walkthrough is in [JSON API](docs/api.md); everything else is in the [documentation index](#documentation).

## <a name="documentation"></a>Documentation
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"require": {
"php": "^8.4.1 || ^8.5",
"laranail/env-kit": "^0.1",
"laranail/package-tools": "^0.1",
"laranail/package-tools": "^0.1.3",
"illuminate/contracts": "^13.0",
"illuminate/http": "^13.0",
"illuminate/routing": "^13.0",
Expand Down
5 changes: 3 additions & 2 deletions docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ While disabled, every API and panel route returns `404` — checked per request,
the surface can be toggled at runtime.

The **in-app surfaces honour the same switch**: the Filament page's `canAccess()` and
the Livewire `env-kit-panel` component both refuse (Filament hides it / the component
403s) unless `enabled` is true — so embedding them anywhere can't bypass the gate.
the Livewire `laranail-env-kit-webui.panel` component (also reachable through its deprecated
`env-kit-panel` alias) both refuse (Filament hides it / the component 403s) unless `enabled`
is true — so embedding them anywhere can't bypass the gate.

## 2. Auth-gated

Expand Down
30 changes: 27 additions & 3 deletions docs/themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ root class; every built-in theme ships `dark:` variants:

## How it works

All themes render one Blade view (`laranail-env-kit-webui::panel`), parameterised by a CSS
All themes render one Blade view (`laranail/env-kit-webui::panel`), parameterised by a CSS
class map — there is no per-theme view duplication. The view is fed an
`EnvKitViewModel` built from the engine (keys/values with secrets masked).

Views answer to both `laranail/env-kit-webui::` (canonical) and `laranail-env-kit-webui::`, over
the same paths, so an override in `resources/views/vendor/laranail-env-kit-webui/` applies to
either. Translations are registered under both forms too. The package's own views translate
through `laranail-env-kit-webui::`, so overrides keep living in
`lang/vendor/laranail-env-kit-webui/`.

## Custom themes

Extend `AbstractThemeAdapter` (supply `name()` + a `classes()` map) and register it
Expand Down Expand Up @@ -77,8 +83,26 @@ public function panel(Panel $panel): Panel
}
```

The page embeds the reactive Livewire panel. (Requires `livewire/livewire`, which
Filament already depends on.)
The page is served at `{panel}/laranail-env-kit-webui` (route name
`filament.{panel}.pages.laranail-env-kit-webui`) and embeds the reactive Livewire panel,
`laranail-env-kit-webui.panel`. (Requires `livewire/livewire`, which Filament already depends
on.) To embed the panel elsewhere:

```blade
@livewire('laranail-env-kit-webui.panel')
```

### Deprecated names

These still work and are removed no earlier than the next minor after 0.1:

| Deprecated | Replacement | How it still works |
|---|---|---|
| Page slug `env-kit` | `laranail-env-kit-webui` | `{panel}/env-kit` redirects to the page, keeping the query string, under the old route name `filament.{panel}.pages.env-kit`. |
| Livewire `env-kit-panel` | `laranail-env-kit-webui.panel` | Still registered for the same component. |

Each raises one `E_USER_DEPRECATED` per process naming the replacement, which Laravel writes to
the `deprecations` log channel when one is configured.

## Laravel Nova

Expand Down
5 changes: 3 additions & 2 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ parameters:
# at runtime — only loaded when a consumer with Nova references it.
- src/Adapters/Nova/EnvKitTool.php
ignoreErrors:
# The `laranail-env-kit-webui::` view namespace is registered at RUNTIME by the service
# provider (package-tools' bootPackageViews()), and PHPStan does not execute that — so
# The `laranail/env-kit-webui::` and `laranail-env-kit-webui::` view namespaces are
# registered at RUNTIME by the service provider (loadViewsFrom() plus package-tools'
# NamespaceForms::mirror()), and PHPStan does not execute that — so
# larastan cannot resolve the literal to a file and reports it as a plain string rather
# than a view-string. Both views do exist: resources/views/panel.blade.php and
# resources/views/livewire/env-kit-panel.blade.php.
Expand Down
2 changes: 1 addition & 1 deletion resources/views/filament/env-kit-page.blade.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<x-filament-panels::page>
@livewire('env-kit-panel')
@livewire('laranail-env-kit-webui.panel')
</x-filament-panels::page>
2 changes: 1 addition & 1 deletion src/Adapters/AbstractThemeAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function render(EnvKitViewModel $viewModel): View
$classes['root'] = trim(($classes['root'] ?? '') . ' dark');
}

return app(ViewFactory::class)->make('laranail-env-kit-webui::panel', [
return app(ViewFactory::class)->make('laranail/env-kit-webui::panel', [
'vm' => $viewModel,
'theme' => $classes,
]);
Expand Down
39 changes: 37 additions & 2 deletions src/Adapters/Filament/EnvKitPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,59 @@

namespace Simtabi\Laranail\EnvKit\WebUI\Adapters\Filament;

use Filament\Panel;
use Filament\Pages\Page;
use Filament\Pages\PageConfiguration;
use Illuminate\Support\Facades\Route;
use Simtabi\Laranail\EnvKit\WebUI\Support\PanelAccess;
use Simtabi\Laranail\EnvKit\WebUI\Support\RegisteredNames;

/**
* A Filament panel page that surfaces the EnvKit editor (the reactive Livewire
* panel) inside a Filament admin panel. Register it via {@see EnvKitPlugin} on
* your panel. Only autoloaded when Filament is installed (the consumer references
* it from their panel config).
*
* The slug is vendor-scoped (`laranail-env-kit-webui`), since Filament keys page
* URLs and route names by it. The old `env-kit` slug still answers: see
* {@see self::registerRoutes()}.
*/
final class EnvKitPage extends Page
{
protected static ?string $navigationLabel = 'EnvKit';

protected static ?string $title = 'EnvKit';

protected static ?string $slug = 'env-kit';
protected static ?string $slug = RegisteredNames::FILAMENT_SLUG;

protected string $view = 'laranail-env-kit-webui::filament.env-kit-page';
protected string $view = 'laranail/env-kit-webui::filament.env-kit-page';

/**
* Register the page, plus the deprecated `env-kit` slug as a redirect to it.
*
* The redirect is registered in the same group as the page, so it gets the
* panel's prefix, tenancy and auth middleware, and takes the page's old
* route name (`filament.<panel>.pages.env-kit`), so a host's
* `route('filament.admin.pages.env-kit')` still generates a working link.
* It is skipped for a configured or clustered page, whose URL never was the
* bare slug.
*
* @deprecated the redirect only; it goes with the old slug, no earlier than
* the next minor after 0.1.
*/
public static function registerRoutes(Panel $panel, ?PageConfiguration $configuration = null): void
{
parent::registerRoutes($panel, $configuration);

if ($configuration !== null || filled(self::getCluster())) {
return;
}

Route::name('pages.')->group(static function (): void {
Route::get('/' . RegisteredNames::LEGACY_FILAMENT_SLUG, RedirectLegacySlug::class)
->name(RegisteredNames::LEGACY_FILAMENT_SLUG);
});
}

/** Honour the same disabled-by-default + gate policy as the HTTP surface. */
public static function canAccess(): bool
Expand Down
47 changes: 47 additions & 0 deletions src/Adapters/Filament/RedirectLegacySlug.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace Simtabi\Laranail\EnvKit\WebUI\Adapters\Filament;

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Simtabi\Laranail\EnvKit\WebUI\Support\RegisteredNames;
use Simtabi\Laranail\EnvKit\WebUI\Support\DeprecationNotices;

/**
* Answers the page's deprecated `{panel}/env-kit` URL with a redirect to
* `{panel}/laranail-env-kit-webui`, keeping the query string.
*
* The target is the request's own path with its last segment replaced, so a
* tenant or domain prefix the panel adds survives without this class knowing
* about it. The page itself still decides access when the redirect lands.
*
* @deprecated exists only for the old slug; goes with it, no earlier than the
* next minor after 0.1.
*/
final class RedirectLegacySlug
{
public function __invoke(Request $request): RedirectResponse
{
DeprecationNotices::once('filament-slug', sprintf(
'laranail/env-kit-webui: the Filament page slug [%s] is deprecated and will be removed no earlier than the next minor after 0.1; use [%s].',
RegisteredNames::LEGACY_FILAMENT_SLUG,
RegisteredNames::FILAMENT_SLUG,
));

$path = rtrim($request->getPathInfo(), '/');
$legacy = '/' . RegisteredNames::LEGACY_FILAMENT_SLUG;

if (str_ends_with($path, $legacy)) {
$path = substr($path, 0, -strlen($legacy));
}

$query = $request->getQueryString();

return new RedirectResponse(
$request->getSchemeAndHttpHost() . $request->getBaseUrl() . $path . '/' . RegisteredNames::FILAMENT_SLUG
. ($query !== null && $query !== '' ? '?' . $query : ''),
);
}
}
2 changes: 1 addition & 1 deletion src/Livewire/EnvKitPanelComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function save(): void

public function render(): View
{
return app(ViewFactory::class)->make('laranail-env-kit-webui::livewire.env-kit-panel');
return app(ViewFactory::class)->make('laranail/env-kit-webui::livewire.env-kit-panel');
}

private function refreshVariables(): void
Expand Down
Loading
Loading