Closed cptiwari20 closed 3 years ago
Where do you want to fetch the data? The boot method and controller constructors obviously won't work because the app doesn't know what tenant is being used yet.
I want to use the data while creating?Editing/deleting new plans and other payment stuff. Mainly for Cashier stuff.
$this->viewResource();
}
....
protected function viewResource(){
View::composer('*', function ($view) {
$this->setConfigData();
if(Schema::hasTable('general_settings')){
$generalSettings = GeneralSettings::findOrFail(1);
$advanceSettings = AdvanceSettings::findOrFail(1);
$view->with([
'tenant_general' => $generalSettings,
'tenant_advance' => $advanceSettings,
]);
}
});
}
This will always run in the central context, because you're accessing the data in a service provider.
But why this is happening, as there is already the middleware has been initialized to prevent access from the central domain. And why this is happening within the constructor function inside the controller. At the same time it is working inside the other methods of controllers.
public function events()
{
return [
// Tenant events
Events\CreatingTenant::class => [],
Events\TenantCreated::class => [
JobPipeline::make([
Jobs\CreateDatabase::class,
Jobs\MigrateDatabase::class,
// Jobs\SeedDatabase::class,
// Your own jobs to prepare the tenant.
// Provision API keys, create S3 buckets, anything you want!
])->send(function (Events\TenantCreated $event) {
return $event->tenant;
})->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production.
],
Events\SavingTenant::class => [],
Events\TenantSaved::class => [],
Events\UpdatingTenant::class => [],
Events\TenantUpdated::class => [],
Events\DeletingTenant::class => [],
Events\TenantDeleted::class => [
JobPipeline::make([
Jobs\DeleteDatabase::class,
])->send(function (Events\TenantDeleted $event) {
return $event->tenant;
})->shouldBeQueued(false), // `false` by default, but you probably want to make this `true` for production.
],
// Domain events
Events\CreatingDomain::class => [],
Events\DomainCreated::class => [],
Events\SavingDomain::class => [],
Events\DomainSaved::class => [],
Events\UpdatingDomain::class => [],
Events\DomainUpdated::class => [],
Events\DeletingDomain::class => [],
Events\DomainDeleted::class => [],
// Database events
Events\DatabaseCreated::class => [],
Events\DatabaseMigrated::class => [],
Events\DatabaseSeeded::class => [],
Events\DatabaseRolledBack::class => [],
Events\DatabaseDeleted::class => [],
// Tenancy events
Events\InitializingTenancy::class => [],
Events\TenancyInitialized::class => [
Listeners\BootstrapTenancy::class,
],
Events\EndingTenancy::class => [],
Events\TenancyEnded::class => [
Listeners\RevertToCentralContext::class,
],
Events\BootstrappingTenancy::class => [],
Events\TenancyBootstrapped::class => [],
Events\RevertingToCentralContext::class => [],
Events\RevertedToCentralContext::class => [],
// Resource syncing
Events\SyncedResourceSaved::class => [
Listeners\UpdateSyncedResource::class,
],
// Fired only when a synced resource is changed in a different DB than the origin DB (to avoid infinite loops)
Events\SyncedResourceChangedInForeignDatabase::class => [],
];
}
public function register()
{
//
}
public function boot()
{
$this->bootEvents();
$this->mapRoutes();
$this->makeTenancyMiddlewareHighestPriority();
$this->viewResource();
}
protected function bootEvents()
{
foreach ($this->events() as $event => $listeners) {
foreach (array_unique($listeners) as $listener) {
if ($listener instanceof JobPipeline) {
$listener = $listener->toListener();
}
Event::listen($event, $listener);
}
}
}
protected function mapRoutes()
{
if (file_exists(base_path('routes/tenant.php'))) {
Route::namespace('App\Http\Controllers')
->group(base_path('routes/tenant.php'));
}
}
protected function makeTenancyMiddlewareHighestPriority()
{
$tenancyMiddleware = [
// Even higher priority than the initialization middleware
Middleware\PreventAccessFromCentralDomains::class,
Middleware\InitializeTenancyByDomain::class,
Middleware\InitializeTenancyBySubdomain::class,
Middleware\InitializeTenancyByDomainOrSubdomain::class,
Middleware\InitializeTenancyByPath::class,
Middleware\InitializeTenancyByRequestData::class,
];
foreach (array_reverse($tenancyMiddleware) as $middleware) {
$this->app[\Illuminate\Contracts\Http\Kernel::class]->prependToMiddlewarePriority($middleware);
}
}
protected function viewResource(){
View::composer('*', function ($view) {
$this->setConfigData();
if(Schema::hasTable('general_settings')){
$generalSettings = GeneralSettings::findOrFail(1);
$advanceSettings = AdvanceSettings::findOrFail(1);
$view->with([
'tenant_general' => $generalSettings,
'tenant_advance' => $advanceSettings,
]);
}
});
}
But why this is happening, as there is already the middleware has been initialized to prevent access from the central domain.
Think about how the Laravel request lifecycle works.
Here you're defining some middleware specifics:
And on the next line, you expect the middleware to be already executed? Of course it's not, Laravel first executes service providers and controller constructors, and only then does it know what middleware to use.
And why this is happening within the constructor function inside the controller. At the same time it is working inside the other methods of controllers.
Please read the early identification docs page.
Thanks
I am having the same issue. I have spent some time reading through all the docs but I am still unable to understand how to make called controllers within routes/tenant.php access the tenant database rather than the central database.
My route looks like this for tenants:
Route::middleware([
'web',
'auth',
InitializeTenancyBySubdomain::class,
PreventAccessFromCentralDomains::class,
])->group(function () {
Route::get('/events', 'EventController@displayEvents')->name('events');
// other routes here
});
I added this __construct function to my EventController (after calling use App\Models\Event, ...
):
public function __construct(Event $events, User $users)
{
$this->users = $users;
$this->events = $events;
}
I have a function within the controller that checks the user role
public function roleCheck()
{
$user = $this->users->find(Auth::id());
if($user->hasAnyRole('Super Administrator', 'Administrator'))
{
return 'admin';
}
elseif($user->hasAnyRole('Client'))
{
return 'client';
}
else
{
return false;
}
}
Here is the Flare of the error. http://flareapp.io/share/17Dn3k9m
Describe the bug
I have created a model and migration called PaymentSettings for both tenants and central domain users.
For central Users = app\Models\System\Admin\PaymentSettings.php For tenants users = app\Models\Tenant\Admin\PaymentSettings.php
I have added the crud operation which is running absolutely fine. I am facing the challenge while setting up the stripe API on boot, in the service provider. When I am fetching the settings data from the database
File:
app\Providers\TenancyServiceProvider.php
As I have already set up the API key, I should get this inside the controllers, but is not so, I am getting the value
null
inside the other controllers when I am callingStripe::getApiKey()
I thought maybe the boot file is not running properly, to I tried to manually write this inside the controllers' constructor inside the tenant's domain as
But the problem did not end here, The value that I am getting is the value from the Central domain not the tenant domain inside the controllers. BUT when I am writing a similar thing inside any other method in the tenant's controller, it's giving the correct value.
Steps to reproduce
Expected behavior
I want to fetch the tenant's database data when I am on the tenant's domain, not the central domain DB data.
Your setup