Skip to content

Commit

Permalink
cleanup, resolve todos, add immediate todos
Browse files Browse the repository at this point in the history
  • Loading branch information
stancl committed Feb 20, 2025
1 parent eac88dc commit a85c88e
Show file tree
Hide file tree
Showing 16 changed files with 72 additions and 91 deletions.
91 changes: 33 additions & 58 deletions assets/TenancyServiceProvider.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,20 @@ public function events()
*/
protected function overrideUrlInTenantContext(): void
{
/**
* Import your tenant model!
*
* \Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper::$rootUrlOverride = function (Tenant $tenant, string $originalRootUrl) {
* $tenantDomain = $tenant instanceof \Stancl\Tenancy\Contracts\SingleDomainTenant
* ? $tenant->domain
* : $tenant->domains->first()->domain;
*
* $scheme = str($originalRootUrl)->before('://');
*
* // If you're using domain identification:
* return $scheme . '://' . $tenantDomain . '/';
*
* // If you're using subdomain identification:
* $originalDomain = str($originalRootUrl)->after($scheme . '://');
* return $scheme . '://' . $tenantDomain . '.' . $originalDomain . '/';
* };
*/
// // Import your tenant model!
// \Stancl\Tenancy\Bootstrappers\RootUrlBootstrapper::$rootUrlOverride = function (Tenant $tenant, string $originalRootUrl) {
// $tenantDomain = $tenant instanceof \Stancl\Tenancy\Contracts\SingleDomainTenant
// ? $tenant->domain
// : $tenant->domains->first()->domain;
// $scheme = str($originalRootUrl)->before('://');

// // If you're using domain identification:
// return $scheme . '://' . $tenantDomain . '/';

// // If you're using subdomain identification:
// $originalDomain = str($originalRootUrl)->after($scheme . '://');
// return $scheme . '://' . $tenantDomain . '.' . $originalDomain . '/';
// };
}

public function register()
Expand All @@ -178,32 +174,17 @@ public function boot()
$this->makeTenancyMiddlewareHighestPriority();
$this->overrideUrlInTenantContext();

/**
* Include soft deleted resources in synced resource queries.
*
* ResourceSyncing\Listeners\UpdateOrCreateSyncedResource::$scopeGetModelQuery = function (Builder $query) {
* if ($query->hasMacro('withTrashed')) {
* $query->withTrashed();
* }
* };
*/

/**
* To make Livewire v3 work with Tenancy, make the update route universal.
*
* Livewire::setUpdateRoute(function ($handle) {
* return RouteFacade::post('/livewire/update', $handle)->middleware(['web', 'universal']);
* });
*/

// if (InitializeTenancyByRequestData::inGlobalStack()) {
// FortifyRouteBootstrapper::$fortifyHome = 'dashboard';
// TenancyUrlGenerator::$prefixRouteNames = false;
// }

if (tenancy()->globalStackHasMiddleware(config('tenancy.identification.path_identification_middleware'))) {
TenancyUrlGenerator::$prefixRouteNames = true;
}
// // Include soft deleted resources in synced resource queries.
// ResourceSyncing\Listeners\UpdateOrCreateSyncedResource::$scopeGetModelQuery = function (Builder $query) {
// if ($query->hasMacro('withTrashed')) {
// $query->withTrashed();
// }
// };

// // To make Livewire v3 work with Tenancy, make the update route universal.
// Livewire::setUpdateRoute(function ($handle) {
// return RouteFacade::post('/livewire/update', $handle)->middleware(['web', 'universal', \Stancl\Tenancy::defaultMiddleware()]);
// });
}

protected function bootEvents()
Expand All @@ -228,10 +209,7 @@ protected function mapRoutes()
->group(base_path('routes/tenant.php'));
}

// Delete this condition when using route-level path identification
if (tenancy()->globalStackHasMiddleware(config('tenancy.identification.path_identification_middleware'))) {
$this->cloneRoutes();
}
// $this->cloneRoutes();
});
}

Expand All @@ -245,16 +223,13 @@ protected function cloneRoutes(): void
/** @var CloneRoutesAsTenant $cloneRoutes */
$cloneRoutes = $this->app->make(CloneRoutesAsTenant::class);

/**
* You can provide a closure for cloning a specific route, e.g.:
* $cloneRoutes->cloneUsing('welcome', function () {
* RouteFacade::get('/tenant-welcome', fn () => 'Current tenant: ' . tenant()->getTenantKey())
* ->middleware(['universal', InitializeTenancyByPath::class])
* ->name('tenant.welcome');
* });
*
* To see the default behavior of cloning the universal routes, check out the cloneRoute() method in CloneRoutesAsTenant.
*/
// // You can provide a closure for cloning a specific route, e.g.:
// $cloneRoutes->cloneUsing('welcome', function () {
// RouteFacade::get('/tenant-welcome', fn () => 'Current tenant: ' . tenant()->getTenantKey())
// ->middleware(['universal', InitializeTenancyByPath::class])
// ->name('tenant.welcome');
// });
// // To see the default behavior of cloning the universal routes, check out the cloneRoute() method in CloneRoutesAsTenant.

$cloneRoutes->handle();
}
Expand Down
8 changes: 3 additions & 5 deletions assets/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@
'cache_store' => null, // null = default
],
],

// todo@docs update integration guides to use Stancl\Tenancy::defaultMiddleware()
],

/**
Expand Down Expand Up @@ -215,7 +213,7 @@
// 'pgsql' => Stancl\Tenancy\Database\TenantDatabaseManagers\PermissionControlledPostgreSQLSchemaManager::class, // Also permission controlled
],

// todo@docblock
// todo0
'drop_tenant_databases_on_migrate_fresh' => false,
],

Expand Down Expand Up @@ -320,7 +318,7 @@
*/
'url_override' => [
// Note that the local disk you add must exist in the tenancy.filesystem.root_override config
// todo@v4 Rename url_override to something that describes the config key better
// todo0 Rename url_override to something that describes the config key better
'public' => 'public-%tenant%',
],

Expand Down Expand Up @@ -356,7 +354,7 @@
* leave asset() helper tenancy disabled and explicitly use tenant_asset() calls in places
* where you want to use tenant-specific assets (product images, avatars, etc).
*/
'asset_helper_tenancy' => false, // todo@rename asset_helper_override?
'asset_helper_override' => false,
],

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Bootstrappers/FilesystemTenancyBootstrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ protected function tenantStoragePath(string $suffix): string

protected function assetHelper(string|false $suffix): void
{
if (! $this->app['config']['tenancy.filesystem.asset_helper_tenancy']) {
if (! $this->app['config']['tenancy.filesystem.asset_helper_override']) {
return;
}

Expand Down
20 changes: 16 additions & 4 deletions src/Bootstrappers/Integrations/FortifyRouteBootstrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
use Stancl\Tenancy\Resolvers\PathTenantResolver;

/**
* Allows customizing Fortify action redirects
* so that they can also redirect to tenant routes instead of just the central routes.
* Allows customizing Fortify action redirects so that they can also redirect
* to tenant routes instead of just the central routes.
*
* Works with path and query string identification.
* This should be used with path/query string identification OR when using Fortify
* universally, including with domains.
*
* When using domain identification, there's no need to pass the tenant parameter,
* you only want to customize the routes being used, so you can set $passTenantParameter
* to false.
*/
class FortifyRouteBootstrapper implements TenancyBootstrapper
{
Expand Down Expand Up @@ -50,6 +55,13 @@ class FortifyRouteBootstrapper implements TenancyBootstrapper
*/
public static array $fortifyRedirectMap = [];

/**
* Should the tenant parameter be passed to fortify routes in the tenant context.
*
* This should be enabled with path/query string identification and disabled with domain identification
*/
public static bool $passTenantParameter = true;

/**
* Tenant route that serves as Fortify's home (e.g. a tenant dashboard route).
* This route will always receive the tenant parameter.
Expand Down Expand Up @@ -82,7 +94,7 @@ protected function useTenantRoutesInFortify(Tenant $tenant): void
$generateLink = function (array $redirect) use ($tenantKey, $tenantParameterName) {
// Specifying the context is only required with query string identification
// because with path identification, the tenant parameter should always present
$passTenantParameter = $redirect['context'] === Context::TENANT;
$passTenantParameter = static::$passTenantParameter && $redirect['context'] === Context::TENANT;

// Only pass the tenant parameter when the user should be redirected to a tenant route
return route($redirect['route_name'], $passTenantParameter ? [$tenantParameterName => $tenantKey] : []);
Expand Down
2 changes: 1 addition & 1 deletion src/Bootstrappers/RootUrlBootstrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class RootUrlBootstrapper implements TenancyBootstrapper
* that are generating URLs in things like mails, the bootstrapper should be used
* just like in any queued job.
*
* todo@revisit
* todo0 update docblock
*/
public static bool $rootUrlOverrideInTests = true;

Expand Down
1 change: 1 addition & 0 deletions src/Database/Concerns/CreatesDatabaseUsers.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ trait CreatesDatabaseUsers
{
public function createDatabase(TenantWithDatabase $tenant): bool
{
// todo0 only continue if this returns true, same below
parent::createDatabase($tenant);

return $this->createUser($tenant->database());
Expand Down
4 changes: 3 additions & 1 deletion src/Database/Concerns/HasPending.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*/
trait HasPending
{
public static string $pendingSinceCast = 'timestamp';

/** Boot the trait. */
public static function bootHasPending(): void
{
Expand All @@ -32,7 +34,7 @@ public static function bootHasPending(): void
/** Initialize the trait. */
public function initializeHasPending(): void
{
$this->casts['pending_since'] = 'timestamp';
$this->casts['pending_since'] = static::$pendingSinceCast;
}

/** Determine if the model instance is in a pending state. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ class MicrosoftSQLDatabaseManager extends TenantDatabaseManager
public function createDatabase(TenantWithDatabase $tenant): bool
{
$database = $tenant->database()->getName();
$charset = $this->connection()->getConfig('charset');
$collation = $this->connection()->getConfig('collation'); // todo check why these are not used

return $this->connection()->statement("CREATE DATABASE [{$database}]");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ protected function grantPermissions(DatabaseConfig $databaseConfig): bool
// Grant permissions to any existing tables. This is used with RLS
// todo@samuel refactor this along with the todo in TenantDatabaseManager
// and move the grantPermissions() call inside the condition in `ManagesPostgresUsers::createUser()`
// but maybe moving it inside $createUser is wrong because some central user may migrate new tables
// while the RLS user should STILL get access to those tables
foreach ($tables as $table) {
$tableName = $table->table_name;

Expand Down
12 changes: 4 additions & 8 deletions src/Events/Contracts/TenantEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@
use Illuminate\Queue\SerializesModels;
use Stancl\Tenancy\Contracts\Tenant;

abstract class TenantEvent // todo we could add a feature to JobPipeline that automatically gets data for the send() from here
abstract class TenantEvent // todo0 we could add a feature to JobPipeline that automatically gets data for the send() from here
{
use SerializesModels;

/** @var Tenant */
public $tenant;

public function __construct(Tenant $tenant)
{
$this->tenant = $tenant;
}
public function __construct(
public Tenant $tenant,
) {}
}
2 changes: 0 additions & 2 deletions src/Exceptions/TenantCouldNotBeIdentifiedByIdException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

declare(strict_types=1);

// todo perhaps create Identification namespace

namespace Stancl\Tenancy\Exceptions;

use Stancl\Tenancy\Contracts\TenantCouldNotBeIdentifiedException;
Expand Down
3 changes: 2 additions & 1 deletion src/Features/UserImpersonation.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static function makeResponse(#[\SensitiveParameter] string|ImpersonationT
return redirect($token->redirect_url);
}

// todo0 test with session scoping
public static function isImpersonating(): bool
{
return session()->has('tenancy_impersonating');
Expand All @@ -62,7 +63,7 @@ public static function isImpersonating(): bool
/**
* Logout from the current domain and forget impersonation session.
*/
public static function leave(): void // todo@name possibly rename
public static function stopImpersonating(): void
{
auth()->logout();

Expand Down
2 changes: 1 addition & 1 deletion src/Middleware/PreventAccessFromUnwantedDomains.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ protected function isCentralDomain(Request $request): bool
return in_array($request->getHost(), config('tenancy.identification.central_domains'), true);
}

// todo@samuel
// todo@samuel technically not an identification middleware but probably ok to keep this here
public function requestHasTenant(Request $request): bool
{
return false;
Expand Down
2 changes: 0 additions & 2 deletions src/Overrides/CacheManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

use Illuminate\Cache\CacheManager as BaseCacheManager;

// todo@move move to Cache namespace?
class CacheManager extends BaseCacheManager
{
/**
Expand Down
2 changes: 1 addition & 1 deletion src/ResourceSyncing/SyncMaster.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Stancl\Tenancy\Database\Contracts\TenantWithDatabase;

// todo@move move all resource syncing-related things to a separate namespace?
// todo@move move all resource syncing-related things to a separate namespace? todo0 seems to be done, confirm EVERYTHING is moved

/**
* @property-read TenantWithDatabase[]|Collection<int, TenantWithDatabase&Model> $tenants
Expand Down
8 changes: 4 additions & 4 deletions tests/TenantAssetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

test('asset helper returns a link to tenant asset controller when asset url is null', function () {
config(['app.asset_url' => null]);
config(['tenancy.filesystem.asset_helper_tenancy' => true]);
config(['tenancy.filesystem.asset_helper_override' => true]);

$tenant = Tenant::create();
tenancy()->initialize($tenant);
Expand All @@ -78,7 +78,7 @@

test('asset helper returns a link to an external url when asset url is not null', function () {
config(['app.asset_url' => 'https://an-s3-bucket']);
config(['tenancy.filesystem.asset_helper_tenancy' => true]);
config(['tenancy.filesystem.asset_helper_override' => true]);

$tenant = Tenant::create();
tenancy()->initialize($tenant);
Expand All @@ -93,7 +93,7 @@
TenancyUrlGenerator::$prefixRouteNames = true;
TenancyUrlGenerator::$passTenantParameterToRoutes = true;

config(['tenancy.filesystem.asset_helper_tenancy' => true]);
config(['tenancy.filesystem.asset_helper_override' => true]);
config(['tenancy.identification.default_middleware' => InitializeTenancyByPath::class]);
config(['tenancy.bootstrappers' => array_merge([UrlGeneratorBootstrapper::class], config('tenancy.bootstrappers'))]);

Expand Down Expand Up @@ -165,7 +165,7 @@

config([
'app.asset_url' => null,
'tenancy.filesystem.asset_helper_tenancy' => false,
'tenancy.filesystem.asset_helper_override' => false,
]);

$tenant = Tenant::create();
Expand Down

0 comments on commit a85c88e

Please sign in to comment.