Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multitenancy with Passport, Scheduling, Filesystem #29

Closed
anwarx4u opened this issue May 29, 2020 · 12 comments
Closed

Multitenancy with Passport, Scheduling, Filesystem #29

anwarx4u opened this issue May 29, 2020 · 12 comments
Labels
enhancement New feature or request

Comments

@anwarx4u
Copy link

Hi,

Great work! I am really very excited to use this package at my running project.

I have read DOCs. I could not find any settings regarding API Passport and scheduling. Doesn't have any specific Settings for managing API requests and managing scheduling jobs?

If I want to use a different File storage directory for each Tenant managing File storage, Does there have any method/settings to maintain this?

Anwar

@freekmurze
Copy link
Member

No, the package does not do this. It allows you to define tasks that should run when switching tenants. If you expect a more batteries included type of package, please check out the alternatives mentioned in the readme.

@anwarx4u
Copy link
Author

anwarx4u commented May 30, 2020

Thank you for your quick response.

However, As I research the packages DOCs, I got well flexibility. So, I will recommend this package for my project. In this case, I need your help to resolve those issues.

FileSystem: For these issues, I can create a new Task for managing the File System easily.
In the makeCurrent, I can write a few code as follows:
config()->set('filesystems.disks.disk_name.root', storage_path("app/public/tenant_{$tenant->id}" ));
config()->set('filesystems.disks.disk_name.url', "/storage/tenant_{$tenant->id}");

Passport: I saw a reference to resolve this.(Not test in this package).
https://medium.com/@wannymiarelli/laravel-multi-tenancy-with-passport-10ce9b6a1c21

Scheduling: In my project, might have 5000+ Tenants in the future.So, I need the best solution so that It does not affect my project performance. Can you provide any hints for that?

I highly request you to review my above possible solution and suggest me the best way.

Thank you in advance.
Anwar

@masterix21
Copy link
Collaborator

@anwardote, it's effortless using tasks.

You can add a "tenant" disk in "config/filesystems.php" file:

'disks' => [
      'tenant' => [
            'visibility' => 'public',
      ],
]

Next, you can create your switch task "FilesystemTask":

class FilesystemTask implements SwitchTenantTask
{
    public function makeCurrent(Tenant $tenant): void
    {
        $this->setTenantFilesystem($tenant);
    }

    public function forgetCurrent(): void
    {
        $this->setTenantFilesystem();
    }

    protected function setTenantFilesystem(?Tenant $tenant = null): void
    {
        config()->set('filesystem.tenant', [
                // your setup for a public disk
        ]);
    }
}

Hope that will help you :)

@anwarx4u
Copy link
Author

@masterix21 , Thank you...

Yea. we can manage Filesystem using Switch Task. But how about Passport and Scheduling?

@masterix21
Copy link
Collaborator

About Passport, I think you can use one of these two approaches.

  1. keep the original Models and use a task to switch the default connection
config()->set('database.default',` 'tenant')
  1. create a task to switch Passport models to custom ones if you're using a tenant
class PassportTask implements SwitchTenantTask
{
    public function makeCurrent(Tenant $tenant): void
    {
        $this->setTenantPassport($tenant);
    }

    public function forgetCurrent(): void
    {
        $this->setTenantPassport();
    }

    protected function setTenantPassport(?Tenant $tenant = null): void
    {
        Passport::useTokenModel(TokenTenantAware::class);
        Passport::useClientModel(ClientTenantAware::class);
        Passport::useAuthCodeModel(AuthCodeTenantAware::class);
        Passport::usePersonalAccessClientModel(PersonalAccessClientTenantAware::class);
    }
}

TokenTenantAware::class extends Token {
    UsesTenantConnection;
}

ClientTenantAware::class extends Client {
    UsesTenantConnection;
}

AuthCodeTenantAware::class extends AuthCode {
    UsesTenantConnection;
}

PersonalAccessClientTenantAware::class extends PersonalAccessClient {
    UsesTenantConnection;
}

@anwarx4u
Copy link
Author

Great solution!

I hope, FileSystem and Passport issues are solved. I will apply your solutions to my real project very soon. Only the Scheduling issue is left to resolve

Thank you again

@masterix21
Copy link
Collaborator

Scheduling is a bit different solution, it depends on what you are doing (or you like to do).

If you are meaning about "jobs", "spatie/laravel-multitenancy" already does the dirty work for you, using "queues_are_tenant_aware_by_default" to true in your config file.

If you are meaning about "schedule:run", it's a bit more complicated, because you must understand what you like to do: is it scheduling for all tenants? Or only for one?

@anwarx4u
Copy link
Author

anwarx4u commented Jun 1, 2020

@masterix21

I am thinking about "schedule: run". Yea it's a bit complex. but I have both types of scheduling.

01. For all tenants: E.g, an announcement for all Tenants. or some scheduling job which should be run in a specific time according to Tenant's Time Zone.

02. For only specific Tenants: E.g, we may need to fire warning/security/billing notification to any/some Tenants.

Noted: In my project, It might have 5000+ Tenants in the future. So, I am searching for the best solution so that It does not affect my project performance.

@freekmurze freekmurze added the enhancement New feature or request label Jun 1, 2020
@freekmurze
Copy link
Member

I'm think that in schedule commands that should be tenant aware you could just loop over de tenants yourself. You can use the eachCurrent method to loop over a tenant collection, it will make each tenant the current one before the callable is executed.

\Spatie\Multitenancy\Models\Tenant::eachCurrent(function(Tenant $tenant) {
    // $tenant is now the active one.
});

@masterix21
Copy link
Collaborator

So, you can create a command (or more), iterate all tenants and push job tenant-aware on the queue (delayed if needed: https://laravel.com/docs/7.x/queues#delayed-dispatching).

Yes, could be 5000 or more Tenants but if your approach is to use the "schedule:run" there are no other solutions.

@anwarx4u
Copy link
Author

anwarx4u commented Jun 1, 2020

@freekmurze
@masterix21

Thanks a lots :-)

@aminraeisi
Copy link

@freekmurze Sorry for the wired question but is this assuming the jobs/failed_jobs table are in /landlord?

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants