1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2026-06-21 18:24:04 +00:00
Commit graph

108 commits

Author SHA1 Message Date
lukinovec
52f6857302 If harden throws an exception, revert connection back to central 2026-05-01 12:08:02 +02:00
github-actions[bot]
fc6a931a32 Fix code style (php-cs-fixer) 2026-05-01 09:50:30 +00:00
lukinovec
665404e7fa Add DatabaseTenancyBootstrapper::$harden
Since It's possible to update tenant's db_name to the central DB or the DB of another tenant. Setting $harden to true prevents tenants from connecting to the wrong databases.
2026-05-01 11:44:56 +02:00
e31249dd09
Prevent mkdir() race conditions in FilesystemTenancyBootstrapper (#1453)
This prevents race conditions that may occur if there are two concurrent
processes trying to create the storage path for the tenant. The
storagePath() method runs during bootstrap() which can easily happen
in two places at once. The race condition specifically occurs in between
the is_dir() check and the mkdir() call, the latter producing an
exception if the dir already exist. We simply ignore any error coming
out of mkdir() and then check for success separately.

We could omit that success check since failure is unlikely and would
only occur due to a server misconfiguration that would manifest itself
in other ways as well, but this way the simple TOC/TOU race condition
is prevented while other errors are still reported.

We apply the same change to the mkdir() in scopeSessions() as the logic
is similar.

Resolves #1452
2026-04-13 23:57:59 +02:00
Victor R
3c0e21b726
[4.x] Filesystem bootstrapper: scoped disk support (#1402)
Fixes #1401

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: Samuel Stancl <samuel@archte.ch>
2025-12-16 23:17:11 +01:00
45cf7029af
globalUrl: useAssetOrigin() instead of setAssetRoot()
This change was prompted by a phpstan failure after a recent update.
While making this change, I noticed we don't need the macro anymore
as useAssetOrigin() was added to the UrlGenerator earlier this year,
simplifying our implementation.
2025-11-14 10:59:31 +01:00
510358b9be
Config: scope_sessions = true only with supported drivers, always throw
With the previous implementation, many users would use the default
config that enables scope_sessions. They would then deploy the app
to production and get the exception there since they use the
`database` session driver which is scoped by a different mechanism.

The idea behind throwing the exception only in prod was to make it
easy to use different setups locally without getting annoying
exceptions, while notifying users that a security feature they enabled
isn't running in production.

However, a better way of doing this is to just throw the exception
consistently in all setups and use a sane default for enabling the
scope_sessions setting based on the SESSION_DRIVER env var.

Users are always encouraged to read the session scoping docs to make
sure their session scoping configuration makes sense for their specific
setup, but this is a good balance for providing solid security out of
the box for most setups without requiring users to configure things
manually.
2025-11-05 14:53:07 +01:00
cab8ecebec
Create tenant storage directories in FilesystemTenancyBootstrapper (#1410)
This is because the CreateTenantStorage listener only runs when
a tenant is created, but in multi-server setups the directory may
need to be created each time a tenant is *used*, not just created.

Also changed the listeners to use TenantEvent instead of specific
events, to make it possible to use them with other events, such as
TenancyBootstrapped.

Also update permission bits in a few mkdir() calls to better scope
data to the current OS user.

Also fix a typo in CacheTenancyBootstrapper (exception message).
2025-11-04 21:16:39 +01:00
0ef4dfd230
DB cache bootstrapper: setConnection() instead of purge() (#1408)
By purging stores, we "detach" existing cache stores from the
CacheManager, making them impossible to adjust in the future.

We also unnecessarily recreate them on every tenancy bootstrap/revert.

A simpler case where this causes problems is defining a RateLimiter in
a service provider. That injects a single cache store into the
rate limiter singleton, which then becomes a completely independent
object after tenancy is initialized due to the purge. This in turn
means the central and tenant contexts share the rate limiter cache
instead of using separate caches as one would expect.
2025-11-04 15:47:15 +01:00
36153a949b
docblocks: change TenantConfig references to TenantConfigBootstrapper 2025-10-30 02:32:17 +01:00
lukinovec
469595534e
[4.x] Make TenancyUrlGenerator inherit the original UrlGenerator's scheme (http or https) (#1390)
Before, when using UrlGeneratorBootstrapper, and your app had a
`https://` url, in tenant context, the url would have the `http://`
scheme.

Now, the bootstrapper makes sure that the TenancyUrlGenerator inherits
the original UrlGenerator's scheme. So if your app has e.g. url
"https://some-url.test", `route('home')` in tenant context will return
"http**s**://some-url.test/home" (originally, you'd get
"http://some-url.test/home" - the original scheme - https - wouldn't be
respected in the tenant context).

This PR addresses the issue reported on Discord
(https://discord.com/channels/976506366502006874/976506736120823909/1399012794514411621).

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
2025-10-28 13:26:50 +01:00
aba7a50619
Minor fixes
The change in SQLiteDatabaseManager wasn't properly saving the
updated internal value.

The check in CacheTenancyBootstrapper wasn't handling that local tests
have a 'testing' environment, not local. However fixing only the
condition would've still added the store to $names which would throw
an exception down the line. We make sure to only throw the exception
in prod, but also make sure to only add the store to $names if it is
supported.
2025-10-22 12:58:45 +02:00
6049ade20e
Fix exception message
Properly retrieve session driver name, previously $name was undefined
2025-10-16 00:15:28 +02:00
74634dfe4b
Session scoping (cache bootstrapper): throw on incompatible driver 2025-10-16 00:05:58 +02:00
a0a9b85982 Refactor DatabaseConfig, minor DB manager improvements, resolve todos
Notable changes:
- CreateUserWithRLSPolicies: Clarify why we're creating a custom
  DatabaseConfing instance
- HasDatabase: Clarify why we're ignoring tenancy_db_connection
- DatabaseConfig: General refactor, clarify the role of the host conn
- SQLiteDatabaseManager: Handle trailing DIRECTORY_SEPARATOR
  in static::$path
- DisallowSqliteAttach: Don't throw any exceptions, just silently fail
  since the class isn't 100% portable
- Clean up todos that are no longer relevant
- Clean up dead code or comments in some database managers
2025-10-13 16:01:34 +02:00
b320f8f33d Add TenantConfigBootstrapper, deprecate Feature implementation
The feature was pretty much a soft-bootstrapper -- it listened
to both Bootstrapped and Reverted. Bootstrappers have a few more
protections in terms of error handling and safe reverting, so there's
no point in (badly) re-implementing bootstrapper functionality within
TenantConfig just so it could be a Feature.

Going forward, all Features should be things that are mostly agnostic
of the tenant state, and especially they should not use bootstrapped/
reverted events. Bootstrappers are simply more appropriate and safe.
2025-09-26 13:49:15 +02:00
33e4a8e4e2 Remove and recategorize todos 2025-08-31 16:57:52 +02:00
ecc3374293 [4.x] Support database cache store tenancy (#1290) (resolve #852)
* Initial implementation (lukinovec)

* Make sure DatabaseCacheBootstrapper runs after DatabaseTenancyBootstrapper, misc wip changes

* Fix withTenantDatabases()

* Add failing test (GlobalCacheTest)

* Configure globalCache's DB stores to use central connection instead of default connection every time it's reinstantiated

* Make GlobalCache facade not cached. Even though it wasn't causing issues
in our existing tests, it likely was flaky, and making it not $cached
makes it now consistent with global_cache() - always getting a new
CacheManager from the globalCache container binding

* Add database connection assertions in GlobalCacheTest

* Run all cached resolver/global cache tests with DatabaseCacheBootstrapper

* Reset adjustCacheManagerUsing in revert() and TestCase

* Reset static $stores property

* Finalize GlobalCache-related changes

* tests: remove pointless cache TTLs

* Refactor DatabaseCacheBootstrapper

* Refactor tests

Co-authored-by: lukinovec <lukinovec@gmail.com>
2025-08-08 00:54:01 +02:00
lukinovec
f308e2f84d
[4.x] Resolve testing todos (#1361)
* Test encrypted cookie identification

* Add Fortify bootstrapper custom query param passing test

* Correct Fortify route bootstrapper test (todo  refactor, convoluted)

* Clarify Fortify bootstrapper test

* Fix encrypted cookie identification test

* Move encrypted cookie assertion to "cookie identification works"

* Cover configured tenant model columns in cached resolver tests

* Refactor testing resolver with default vs custom tenant model name config

* Delete resolved todo

* Make code more concise

* Keep initial formatting (minimize diff noise)

* Make dataset/helper method parameter clearer

* Clarify fortify test

* Clarify assertions, improve comments

* Delete excessive comments, make existing comments consistent and clearer

* Make cached resolver test file clearer, update outdated comments

* Use the tenant model column term consistently

* FIx inconsistencies

* Provide more info in comment

* make comment more clear

* static property reset

---------

Co-authored-by: Samuel Štancl <samuel@archte.ch>
2025-08-03 23:21:03 +02:00
d8af9b4b43 remove JobBatchBootstrapper 2025-07-10 01:08:49 +02:00
5f7fd38e5a
[4.x] URL generation, request data identification improvements (#1357)
* UrlGenerator: set defaults based on config; request data: move config to config file+resolver

* Claude code adjustments

* improve request data tests, simplify complex test in UrlGeneratorBootstrapperTest

* url generator test: test changing tenant parameter name

* request data identification: add tenant_model_column configuration

* defaultParameterNames -> passQueryParameter

* move comment

* minor refactor in PathIdentificationTest, expand CLAUDE.md to include early identification section

* Fix COLOR_FLAG

* improve test name

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* TenancyUrlGenerator: add a check for queryParameterName being null

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix code style (php-cs-fixer)

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-02 03:43:47 +02:00
657e165cc8
[4.x] Cleanup (#1317)
* cleanup, resolve todos, add immediate todos

* Improve path_identification_middleware docblock

* rename leave() method in tests

* wip fix hardcoded values making assumptions about the parameters used in routing

* defaultParameterNames

* fix CreatesDatabaseUsers return values

* $tenant -> tenant()

* resolve more todos

* make comment block a complete block

* Correct useTenantRoutesInFortify(), delete unused import

* test fixes

* remove todos

* remove JobPipeline todo

* simplify comment example

* remove todo

* fix VERSION_PREFIX in queue.yml

---------

Co-authored-by: lukinovec <lukinovec@gmail.com>
2025-02-20 20:49:09 +01:00
lukinovec
cecf07a8c9
[4.x] Add tenant parameter to defaults() in UrlGeneratorBootstrapper (#1311)
* Pass tenant parameter using defaults in UrlGeneratorBootstrapper, update tests accordingly (wip)

* Fix code style (php-cs-fixer)

* Update bootstrapper

* Improve TenancyUrlGenerator docblocks

* Improve bootstrapper/TenancyUrlGenerator tests (WIP)

* Improve route() name prefixing test

* Keep  `UrlGeneratorBootstrapper::$addTenantParameterToDefaults` disabled by default

* Add `$override` functionality  to TenancyUrlGenerator

* Test $override functionality, update new defaults in the bootstrapper tests

* Fix code style (php-cs-fixer)

* Update comments

* Update routeNameOverride()

* cleanup

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
2025-02-14 13:57:29 +01:00
lukinovec
8b131ed647
Allow overriding root URL in tests by default (#1296)
* Allow overriding root URL in tests by default

* Add todo@revisit
2025-01-17 10:20:40 +01:00
Samuel Štancl
5d3b3d3c21
[4.x] Improve RootUrl and UrlGenerator bootstrappers (#1294)
* Make RootUrlBootstrapper run ONLY in CLI by default (add $rootUrlOverrideInTests), work with resolved UrlGenerator

* Make resolving 'url' return a pre-created generator instance instead of creating it on every app('url') call

* Take care of doubling tenant keys in TenancyUrlGenerator, add regression test for using UrlGenerator and RootUrl bootstrappers together

* Fix code style (php-cs-fixer)

* refactor RootUrlBootstrapper

* add docblock

* clarify docblock

* simplify test: use concrete values instead of overly dynamic code

* Fix bootstrapper order in test, add url('/') assertion

* Use $this->app instead of app()

* Improve TenancyUrlGenerator and RootUrlBootstrapperTest clarity

* Revert attempt to maintain compatibility between the two bootstrappers

* Delete bootstrapper combining test

* Fix code style (php-cs-fixer)

---------

Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
2025-01-16 10:30:06 +01:00
Samuel Štancl
8f958d5779
[4.x] Queue logic refactor (#1289)
* simplify QueueTenancyBootstrapper

* wip: add persistent queue bootstrapper, minor testcase refactor

* ci: run persistent queue tests

* simplify persistent queue bootstrapper

* Fix code style (php-cs-fixer)

* phpstan fixes, clarify previousTenant use

* remove false positive regression test

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-14 13:49:16 +01:00
Márk Magyar
79f740d057
[4.x] General code cleanup (#1278)
* Declare sensitive parameters as sensitive

... just so that they don't show up in logs

* Remove unnecessary null-coalescing

* Simplify return

* Merge isset() calls

* Inline return

* Use nullsafe operator

* Simplify if-else branches

* Use direct empty string comparison instead of strlen()

* Add missing type

* Change interface as events expect a TenantWithDatabase not just a Tenant

* Narrow typehint

* Remove redundant type casts

* Fix style with php-cs-fixer

* Fix typos

* Revert unwanted if-else simplification

* fix phpstan errors

* narrow type

---------

Co-authored-by: Samuel Štancl <samuel@archte.ch>
2024-12-31 00:35:46 +01:00
eff41553d7 deprecate JobBatchBootstrapper 2024-12-27 21:33:44 +01:00
Samuel Štancl
85bdbd57f7
Fix pullFromPendingPool() behavior (#70) 2024-11-25 04:44:39 +01:00
lukinovec
2c0f61585d
Make RootUrlBootstrapper only have an effect in CLI (#58)
* Interrupt RootUrlBootstrapper's bootstrap() execution if the app isn't running in console, add docblock

* Improve overrideUrlInTenantContext() documentation [ci skip]

* Improve RootUrlBootstrapper [ci skip]
2024-08-28 00:42:36 +02:00
590360bf0d broadcasting config bootstrapper: add reverb preset 2024-07-04 20:52:06 +02:00
252e337ef8 broadcast channel prefix bootstrapper: add reverb() method 2024-07-04 20:38:23 +02:00
Samuel Štancl
7317d2638a
Postgres RLS + permission controlled database managers (#33)
This PR adds Postgres RLS (trait manager + table manager approach) and permission controlled managers for PostgreSQL.

---------

Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
2024-04-24 22:32:49 +02:00
83b1ae1aea change default cookie name, add todos 2024-04-15 03:11:11 +02:00
e727e07212 redis bootstrapper: support clusters (#1207) 2024-04-12 01:05:46 +02:00
630f404227 add assertion, update todos 2024-04-10 03:35:57 +02:00
Samuel Štancl
eecf6f21c8
Cache prefixing logic rewrite, session scoping improvements, tests refactor (#43)
* Run cache tests on all supported drivers

* update ci healthcheck for memcached

* remove memcached healthcheck

* fix typos in test comments, expand internal.md [ci skip]

* add empty line [ci skip]

* switch to using $store->setPrefix()

* add dynamodb

* refactor try-finally to try-catch

* remove unnecessary clearResolvedInstances() call

* add dual Cache:: and cache() assertions

* add apc

* Flush APCu cache in test setup

* Revert "add dual Cache:: and cache() assertions"

This reverts commit a0bab162fbe2dd0d25e7056ceca4fb7ce54efc77.

* phpstan fix

* Add logic for scoping 'file' disks to FilesystemTenancyBootstrapper

* minor changes, add todos

* refactor how the session.connection is used in the DB session bootstrapper

* add session forgery prevention logic to the db session bootstrapper

* only use the fs bootstrapper for file disk in 'cache data is separated' dataset

* minor session scoping test changes

* Add session scoping logic to FilesystemTenancyBootstrapper, correctly update disk roots even with storage_path_tenancy disabled

* Fix code style (php-cs-fixer)

* update docblock

* make not-null check more explicit

* separate bootstrapper tests, fix swapped test names for two tests

* refactor cache bootstrapper tests

* resolve global cache todo

* expand tests: session separation tests, more filesystem separation assertions; change prefix_base-type config keys to templates/formats

* add apc session scoping test, various session separation bugfixes

* phpstan + minor logic fixes

* prefix_format -> prefix

* fix database session separation test

* revert composer.json changes, update laravel dependencies to expected next release

* only run session scoping logic in cache bootstrapper for redis, memcached, dynamodb, apc; update gitattributes

* tenancy.central_domains -> tenancy.identification.central_domains

* db session separation test: add datasets

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
2024-04-09 20:40:27 +02:00
Samuel Štancl
d9ca3cec38
Misc test fixes (#44)
* Add suffix_storage_path test

* Get filesystem bootstrapper coverage to 100%

* Delete enabling DB bootstrapper in TestCase

* Complete most of test todos

* Complete last tests todo

* Fix docblock

* add todo

---------

Co-authored-by: lukinovec <lukinovec@gmail.com>
2024-04-06 19:17:34 +02:00
1d80604cff Enable single_line_empty_body phpcsfixer rule 2024-04-02 04:31:03 +02:00
Samuel Štancl
a41ad69023
Filesystem logic refactor, improved defaults for cache tenancy (#42)
* refactor FilesystemTenancyBootstrapper

* clean up tests and improve coverage

* minor maintenance mode changes

* Improve tenants:migrate --skip-failing logic

* make tenants:migrate output consistently formatted

* minor RootUrlBootstrapper + misc changes

* cache bootstrapper-related improvements

* Fix code style (php-cs-fixer)

* misc refactor

* Fix code style (php-cs-fixer)

* add %original_storage_path% to fs bootstrapper, improve default config for cache

* rename method

* inject concrete implementations where needed instead of abstracts

* Fix code style (php-cs-fixer)

* refactor DealsWithTenantSymlinks

* remove obsolete phpstan ignore

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
2024-04-02 04:26:10 +02:00
Samuel Štancl
9f94505cb4
Rename bootstrappers (#40)
* SessionTenancyBootstrapper -> DatabaseSessionBootstrapper

* FortifyRouteTenancyBootstrapper -> FortifyRouteBootstrapper

* BatchTenancyBootstrapper -> JobBatchBootstrapper

* ScoutTenancyBootstrapper -> ScoutPrefixBootstrapper, also fix logic and remove todo

* MailTenancyBootstrapper -> MailConfigBootstrapper

* PrefixCacheTenancyBootstrapper -> CacheTenancyBootstrapper

* remove todo

* improve config file
2024-03-28 03:18:23 +01:00
1d42f33d34 better defaults 2024-03-24 04:28:11 +01:00
6c5bde7d07 add todo 2024-03-20 12:23:29 +01:00
a0da54cfdc categorize todos 2024-03-12 17:29:00 +01:00
a430b1de29 Merge remote-tracking branch 'origin/master' into merge-public-repo-master 2024-02-10 21:55:54 +01:00
lukinovec
222bbe4c02
Final filesystem-related changes (#25)
* Change %tenant_id% to %tenant%

* ID -> key

---------

Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
2024-02-10 19:13:02 +01:00
Samuel Štancl
00a00a2aff
Pass BroadcastManager to override closures (#23)
* pass BroadcastManager to override closures

* Improve the broadcaster override syntax in the bootstrapper test

* remove unnecessary return

---------

Co-authored-by: lukinovec <lukinovec@gmail.com>
2023-12-20 12:23:37 +01:00
lukinovec
ea5a7463b8
Allow mapping nested tenant properties to mail config (#20)
* Use data_get() to allow mapping nested tenant attributes to mail config

* Fix code style (php-cs-fixer)

* Test the data_get() change

* Improve code, add info to docblock

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
2023-12-18 12:42:03 +01:00
lukinovec
ca400b51d2 Fix global/central channel terminology 2023-12-13 19:11:18 +01:00
lukinovec
4953c69fd8
Update path identification and Fortify integration-related logic (#13)
* Add commented UrlBinding + FortifyRouteTenancy bootstrappers to the config

* Improve FortifyRoute bootstrapper docblock

* Rename bootstrappers

* Complete renaming

* Pass defaults of the original URL generator to the new one

* Fix URL generator-related test (query string id test WIP)

* Fix code style (php-cs-fixer)

* Make Fortify bootstrapper not depend on the UrlGenerator bootstrapper, update comments

* Fix testing UrlGenerator bootstrapper

* Update TenancyUrlGenerator annotations

* Pass tenant parameter manually in Fortify bootstrapper

* Properly test TenancyUrlGenerator functionality

* Get rid of query string in Fortify bootstrapper

* Fix code style (php-cs-fixer)

* Delete outdated comment

* Improve comment

* Improve before/afterEach

* Encourage passing parameters using TenancyUrlGenerator instead of URL::defaults()

* Delete rest of defaulting logic

* Fix code style (php-cs-fixer)

* Delete test group

* Update ForgetTenantParameter docblock

* Update passTenantParameterToRoutes annotation

* Complete todo in test

* Improve test

* Update comment

* Improve comment

* Add keepQueryParameters bool to Fortify bootstrapper

* Test keepQueryParameters

* minor docblock update

* minor docblock changes

* Delete extra import

* Update src/Overrides/TenancyUrlGenerator.php

Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>

* Improve comment

* Rename test

* Update bypass parameter-related test comments

* Fix merge

* Rename $keepQueryParameters

* Add docblock

* Add comment

* Refactor Fortify bootstrapper

* Fix code style (php-cs-fixer)

* Fix comment

* Skip Fortify bootstrapper test

* minor code improvements

* Improve fortify bootstrapper test

* Add Fortify bootstrapper annotation, improve code

* Fix code style (php-cs-fixer)

* Add commenet

* Complete resource syncing todo (cleanup not needed)

* Delete incorrect namespace

* Complete route context trait name todo

* Fix code style (php-cs-fixer)

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
2023-11-26 21:08:41 +01:00