mirror of
https://github.com/archtechx/tenancy.git
synced 2026-03-22 21:14:05 +00:00
Merge branch 'archtechx:3.x' into 3.x
This commit is contained in:
commit
32e3b375ca
10 changed files with 114 additions and 19 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
|
@ -16,12 +16,13 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- laravel: 9
|
||||
php: "8.0"
|
||||
- laravel: 10
|
||||
php: "8.1"
|
||||
- laravel: 11
|
||||
php: "8.3"
|
||||
- laravel: 12
|
||||
php: "8.3"
|
||||
# Ideally we'd run at least one of these on PHP 8.4, however the Dockerfile seems to require some changes for that
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
|
|||
35
.github/workflows/queue.yml
vendored
Normal file
35
.github/workflows/queue.yml
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
name: Queue tests
|
||||
|
||||
on:
|
||||
- push
|
||||
|
||||
jobs:
|
||||
queue:
|
||||
name: Queue application tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Prepare composer version constraint prefix
|
||||
run: |
|
||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
||||
# For refs like "refs/tags/v3.9.0", remove "refs/tags/v" prefix to get just "3.9.0"
|
||||
VERSION=${GITHUB_REF#refs/tags/v}
|
||||
echo "VERSION_PREFIX=${VERSION}" >> $GITHUB_ENV
|
||||
else
|
||||
BRANCH=${GITHUB_REF#refs/heads/}
|
||||
if [[ $BRANCH =~ ^[0-9]\.x$ ]]; then
|
||||
# Branches starting with %d.x need to use -dev suffix
|
||||
echo "VERSION_PREFIX=${BRANCH}-dev" >> $GITHUB_ENV
|
||||
else
|
||||
# All other branches use dev-${branch} prefix
|
||||
echo "VERSION_PREFIX=dev-${BRANCH}" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Clone test suite
|
||||
run: git clone https://github.com/archtechx/tenancy-queue-tester
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tenancy-queue-tester
|
||||
TENANCY_VERSION=${VERSION_PREFIX}#${GITHUB_SHA} ./setup.sh
|
||||
TENANCY_VERSION=${VERSION_PREFIX}#${GITHUB_SHA} ./test.sh
|
||||
|
|
@ -194,6 +194,6 @@ return [
|
|||
*/
|
||||
'seeder_parameters' => [
|
||||
'--class' => 'DatabaseSeeder', // root seeder class
|
||||
// '--force' => true,
|
||||
// '--force' => true, // This needs to be true to seed tenant databases in production
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -12,15 +12,15 @@
|
|||
"require": {
|
||||
"php": "^8.0",
|
||||
"ext-json": "*",
|
||||
"illuminate/support": "^9.0|^10.0|^11.0",
|
||||
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||
"facade/ignition-contracts": "^1.0.2",
|
||||
"ramsey/uuid": "^4.7.3",
|
||||
"stancl/jobpipeline": "^1.6.2",
|
||||
"stancl/virtualcolumn": "^1.3.1"
|
||||
"stancl/jobpipeline": "^1.8.0",
|
||||
"stancl/virtualcolumn": "^1.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/framework": "^9.0|^10.0|^11.0",
|
||||
"orchestra/testbench": "^7.0|^8.0|^9.0",
|
||||
"laravel/framework": "^10.0|^11.0|^12.0",
|
||||
"orchestra/testbench": "^8.0|^9.0|^10.0",
|
||||
"league/flysystem-aws-s3-v3": "^3.12.2",
|
||||
"doctrine/dbal": "^3.6.0",
|
||||
"spatie/valuestore": "^1.3.2"
|
||||
|
|
|
|||
|
|
@ -18,13 +18,16 @@ trait InvalidatesResolverCache
|
|||
|
||||
public static function bootInvalidatesResolverCache()
|
||||
{
|
||||
static::saved(function (Tenant $tenant) {
|
||||
$invalidateCache = static function (Tenant $tenant) {
|
||||
foreach (static::$resolvers as $resolver) {
|
||||
/** @var CachedTenantResolver $resolver */
|
||||
$resolver = app($resolver);
|
||||
|
||||
$resolver->invalidateCache($tenant);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
static::saved($invalidateCache);
|
||||
static::deleting($invalidateCache);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,13 +21,16 @@ trait InvalidatesTenantsResolverCache
|
|||
|
||||
public static function bootInvalidatesTenantsResolverCache()
|
||||
{
|
||||
static::saved(function (Model $model) {
|
||||
$invalidateCache = static function (Model $model) {
|
||||
foreach (static::$resolvers as $resolver) {
|
||||
/** @var CachedTenantResolver $resolver */
|
||||
$resolver = app($resolver);
|
||||
|
||||
$resolver->invalidateCache($model->tenant);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
static::saved($invalidateCache);
|
||||
static::deleting($invalidateCache);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ class ModelNotSyncMasterException extends Exception
|
|||
{
|
||||
public function __construct(string $class)
|
||||
{
|
||||
parent::__construct("Model of $class class is not an SyncMaster model. Make sure you're using the central model to make changes to synced resources when you're in the central context");
|
||||
parent::__construct("Model of $class class is not a SyncMaster model. Make sure you're using the central model to make changes to synced resources when you're in the central context.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class UserImpersonation implements Feature
|
|||
|
||||
public function bootstrap(Tenancy $tenancy): void
|
||||
{
|
||||
$tenancy->macro('impersonate', function (Tenant $tenant, string $userId, string $redirectUrl, string $authGuard = null): ImpersonationToken {
|
||||
$tenancy->macro('impersonate', function (Tenant $tenant, string $userId, string $redirectUrl, ?string $authGuard = null): ImpersonationToken {
|
||||
return ImpersonationToken::create([
|
||||
'tenant_id' => $tenant->getTenantKey(),
|
||||
'user_id' => $userId,
|
||||
|
|
@ -32,10 +32,10 @@ class UserImpersonation implements Feature
|
|||
* Impersonate a user and get an HTTP redirect response.
|
||||
*
|
||||
* @param string|ImpersonationToken $token
|
||||
* @param int $ttl
|
||||
* @param int|null $ttl
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public static function makeResponse($token, int $ttl = null): RedirectResponse
|
||||
public static function makeResponse($token, ?int $ttl = null): RedirectResponse
|
||||
{
|
||||
$token = $token instanceof ImpersonationToken ? $token : ImpersonationToken::findOrFail($token);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,10 +40,8 @@ class InitializeTenancyByPath extends IdentificationMiddleware
|
|||
return $this->initializeTenancy(
|
||||
$request, $next, $route
|
||||
);
|
||||
} else {
|
||||
throw new RouteIsMissingTenantParameterException;
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
throw new RouteIsMissingTenantParameterException;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||
namespace Stancl\Tenancy\Tests;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedOnDomainException;
|
||||
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
|
||||
use Stancl\Tenancy\Tests\Etc\Tenant;
|
||||
|
||||
|
|
@ -80,6 +81,33 @@ class CachedTenantResolverTest extends TestCase
|
|||
$this->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cache_is_invalidated_when_the_tenant_is_deleted()
|
||||
{
|
||||
$tenant = Tenant::create();
|
||||
$tenant->createDomain([
|
||||
'domain' => 'acme',
|
||||
]);
|
||||
|
||||
DB::enableQueryLog();
|
||||
|
||||
DomainTenantResolver::$shouldCache = true;
|
||||
|
||||
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||
DB::flushQueryLog();
|
||||
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||
$this->assertEmpty(DB::getQueryLog()); // empty
|
||||
|
||||
$tenant->delete();
|
||||
DB::flushQueryLog();
|
||||
|
||||
$this->assertThrows(function () {
|
||||
app(DomainTenantResolver::class)->resolve('acme');
|
||||
}, TenantCouldNotBeIdentifiedOnDomainException::class);
|
||||
|
||||
$this->assertNotEmpty(DB::getQueryLog()); // not empty - cache cleared so the DB was queried
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cache_is_invalidated_when_a_tenants_domain_is_changed()
|
||||
{
|
||||
|
|
@ -109,4 +137,31 @@ class CachedTenantResolverTest extends TestCase
|
|||
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('bar')));
|
||||
$this->assertNotEmpty(DB::getQueryLog()); // not empty
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function cache_is_invalidated_when_a_tenants_domain_is_deleted()
|
||||
{
|
||||
$tenant = Tenant::create();
|
||||
$tenant->createDomain([
|
||||
'domain' => 'acme',
|
||||
]);
|
||||
|
||||
DB::enableQueryLog();
|
||||
|
||||
DomainTenantResolver::$shouldCache = true;
|
||||
|
||||
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||
DB::flushQueryLog();
|
||||
$this->assertTrue($tenant->is(app(DomainTenantResolver::class)->resolve('acme')));
|
||||
$this->assertEmpty(DB::getQueryLog()); // empty
|
||||
|
||||
$tenant->domains->first()->delete();
|
||||
DB::flushQueryLog();
|
||||
|
||||
$this->assertThrows(function () {
|
||||
app(DomainTenantResolver::class)->resolve('acme');
|
||||
}, TenantCouldNotBeIdentifiedOnDomainException::class);
|
||||
|
||||
$this->assertNotEmpty(DB::getQueryLog()); // not empty - cache cleared so the DB was queried
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue