tenancy / multi-tenant

Run multiple websites using the same Laravel installation while keeping tenant specific data separated for fully independent multi-domain setups, previously github.com/hyn/multi-tenant
https://tenancy.dev
MIT License
2.56k stars 394 forks source link

5.4 Upgrade - Need help #752

Closed xalunda closed 5 years ago

xalunda commented 5 years ago

Good afternoon

Following the upgrade guide, I added the key into config/tenancy.php file:

'key' => env('TENANCY_KEY', env('APP_KEY')),

Changed the following on my composer.json:

"require": {
    ...
    "hyn/multi-tenant": "5.4.0",
    "laravel/framework": "5.8.*",
    ...
},

I'm correctly on php 7.2.1


The main hostname example.com works fine. Whenever I try a tenant website sub.example.com, I get this error that I can't seem to debug.

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'd3442a527d7b4b08a8053755b87151f1.users' doesn't exist (SQL: select * from `users` where `id` = 1 limit 1)

Looks like some middleware is trying to authenticate the user through it's own database.

Information


tenancy.php config

<?php
use Hyn\Tenancy\Database\Connection;

return [
    'key' => env('TENANCY_KEY', env('APP_KEY')),

    'models' => [
        // Must implement \Hyn\Tenancy\Contracts\Hostname
        'hostname' => \App\Models\Hostname::class,

        // Must implement \Hyn\Tenancy\Contracts\Website
        'website' => \App\Models\Project::class
    ],
    'middleware' => [
        // The eager identification middleware.
        \Hyn\Tenancy\Middleware\EagerIdentification::class,

        // The hostname actions middleware (redirects, https, maintenance).
        \Hyn\Tenancy\Middleware\HostnameActions::class,
    ],
    'website' => [
        'disable-random-id' => false,
        'random-id-generator' => Hyn\Tenancy\Generators\Uuid\ShaGenerator::class,
        'uuid-limit-length-to-32' => env('LIMIT_UUID_LENGTH_32', false),
        'disk' => 'local-tenant',
        'auto-create-tenant-directory' => true,
        'auto-rename-tenant-directory' => true,
        'auto-delete-tenant-directory' => false,
        'cache' => 10,
    ],
    'hostname' => [
        'default' => env('TENANCY_DEFAULT_HOSTNAME'),
        'auto-identification' => env('TENANCY_AUTO_HOSTNAME_IDENTIFICATION', true),
        'early-identification' => env('TENANCY_EARLY_IDENTIFICATION', true),
        'abort-without-identified-hostname' => env('TENANCY_ABORT_WITHOUT_HOSTNAME', false),
        'cache' => 10,
        'update-app-url' => false,
    ],
    'db' => [
        'default' => env('TENANCY_DEFAULT_CONNECTION'),
        'system-connection-name' => env('TENANCY_SYSTEM_CONNECTION_NAME', Connection::DEFAULT_SYSTEM_NAME),
        'tenant-connection-name' => env('TENANCY_TENANT_CONNECTION_NAME', Connection::DEFAULT_TENANT_NAME),
        'tenant-division-mode' => env('TENANCY_DATABASE_DIVISION_MODE', 'database'),
        'password-generator' => Hyn\Tenancy\Generators\Database\DefaultPasswordGenerator::class,
        'tenant-migrations-path' => database_path('migrations/tenants'),
        'tenant-seed-class' => TenantDatabaseSeeder::class,
        'auto-create-tenant-database' => true,
        'auto-create-tenant-database-user' => true,
        'tenant-database-user-privileges' => null,
        'auto-rename-tenant-database' => true,
        'auto-delete-tenant-database' => env('TENANCY_DATABASE_AUTO_DELETE', false),
        'auto-delete-tenant-database-user' => env('TENANCY_DATABASE_AUTO_DELETE_USER', false),
        'force-tenant-connection-of-models' => [
           // App\AccountingGroupAccount::class
        ],
        'force-system-connection-of-models' => [
            //App\User::class
        ],
    ],
    'routes' => [
        'path' => base_path('routes/tenants.php'),
        'replace-global' => false,
    ],
    'folders' => [
        'config' => [
            'enabled' => true,
            'blacklist' => ['database', 'tenancy', 'webserver'],
        ],
        'routes' => [
            'enabled' => true,
            'prefix' => null,
        ],
        'trans' => [
            'enabled' => true,
            'override-global' => true,
            'namespace' => 'tenant',
        ],
        'vendor' => [
            'enabled' => true,
        ],
        'media' => [
            'enabled' => true,
        ],
        'views' => [
            'enabled' => true,
            'namespace' => null,
            'override-global' => true,
        ]
    ]
];

webserver.php config

<?php
return [
    'apache2' => [
        'enabled' => true,
        'ports' => [
            'http' => 80,
            'https' => 443
        ],
        'generator' => \Hyn\Tenancy\Generators\Webserver\Vhost\ApacheGenerator::class,
        'view' => 'tenancy.generators::webserver.apache.vhost',
        'disk' => null,

        'paths' => [
            'vhost-files' => [
                'storage/app/tenancy/webserver/apache2/'
            ],
            'actions' => [
                'exists' => '/etc/init.d/apache2',
                'test-config' => true,
                'reload' => null
            ]
        ]
    ],
    'nginx' => [
        'enabled' => false,
        'php-sock' => 'unix:/var/run/php/php7.1-fpm.sock',
        'ports' => [
            'http' => 80,
            'https' => 443
        ],
        'generator' => \Hyn\Tenancy\Generators\Webserver\Vhost\NginxGenerator::class,
        'view' => 'tenancy.generators::webserver.nginx.vhost',
        'disk' => null,

        'paths' => [
            'vhost-files' => [
                '/etc/nginx/sites-enabled/'
            ],
            'actions' => [
                'exists' => '/etc/init.d/nginx',
                'test-config' => '/etc/init.d/nginx configtest',
                'reload' => '/etc/init.d/nginx reload'
            ]
        ]
    ]
];

open-collective-bot[bot] commented 5 years ago

Hey :wave:,

Thank you for using our package.

We firmly believe that open sourcing our code improves the developer experience. In a pursuit to continue our work, help us by donating to our collective! :heart:

Issues opened by backers of our Open Collective will automatically labelled with the "backer" tag for priority response and resolve times.

https://opencollective.com/tenancy

Plytas commented 5 years ago

Can you confirm that database d3442a527d7b4b08a8053755b87151f1 exists and it fully migrated?

xalunda commented 5 years ago

Hi,

Thanks for your fast reply

Yes everything is correct. All I did was change the composer and composer update

On Fri, Mar 15, 2019, 1:12 PM Vytautas Smilingis notifications@github.com wrote:

Can you confirm that database d3442a527d7b4b08a8053755b87151f1 exists and it fully migrated?

β€” You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/hyn/multi-tenant/issues/752#issuecomment-473280279, or mute the thread https://github.com/notifications/unsubscribe-auth/ACNXvXjDxWW0A3fgNGA1754Fx81lkWWEks5vW5wmgaJpZM4b2bAH .

Plytas commented 5 years ago

Try running php artisan tenancy:key:update command.

xalunda commented 5 years ago

Got no output The key did not change The error remains

xalunda commented 5 years ago

That's the content of Hyn\Tenancy\Commands\UpdateKeyCommand.php

class UpdateKeyCommand extends Command
{
    use DispatchesEvents;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'tenancy:key:update';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Update tenant users passwords.';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->emitEvent(new KeyUpdated());
    }
}

This doesn't do anything

Plytas commented 5 years ago

That command simply iterates over all tenants and updates their database user password. What's weird to me that the error doesn't complain about wrong password, but it says, that it can't find users table inside the tenant database.

Plytas commented 5 years ago

Can you post a screenshot of that database in question and tables?

xalunda commented 5 years ago

Here is the database screenshot Screen Shot 2019-03-15 at 1 27 32 PM I'm not allowed to post the tables, sorry. Is there something specific to check about it ?

Plytas commented 5 years ago

If you are sure that users table exist on that database, can you post a full trace of the error?

xalunda commented 5 years ago

The d3442a527d7b4b08a8053755b87151f1 is a tenant database. My users table has always been in the system database. There is no users table in my tenants databases

Plytas commented 5 years ago

That makes more sense now. Does your user model have UsesSystemConnection trait?

xalunda commented 5 years ago

HOLY MOLLY!

It did not! It works now! Wondering how it worked until then though.

You absolutely made my day! Thanks a lot πŸ₯‡

Plytas commented 5 years ago

Did you change any other config options, like tenancy.db.default?

xalunda commented 5 years ago

tenancy.db.default => env('TENANCY_DEFAULT_CONNECTION')

.env file: TENANCY_DEFAULT_CONNECTION=tenant

I did not change those values

xalunda commented 5 years ago

Looks like laravel Passport also needs to be told to use the correct database:

'd3442a527d7b4b08a8053755b87151f1.oauth_personal_access_clients'

Any idea were to do that ?

bkintanar commented 5 years ago

@xalunda you can extend the passport related models and add the UsesTenantConnection to the extended models and then read here on how to override default models

or add this to your AppServiceProvider's boot method

$env = app(Environment::class);

if ($fqdn = optional($env->hostname())->fqdn) {
    config(['database.default' => 'tenant']);
}
Plytas commented 5 years ago

By specifying tenant as default it forces every model to use tenant connection. Not sure why it worked for you before. I would set the default connection to system and then add UsesTenantConnection to your models that need to connect to tenant database.

Otherwise you could try forcing 3rd party model connection through config: https://github.com/hyn/multi-tenant/blob/458fc0220420ecfe6fd11818098c442c48aa910f/assets/configs/tenancy.php#L292-L304 Though I see there's a reported issue on that #751

xalunda commented 5 years ago

So, I can set default to system in the AppServiceProvider? Every single tenant model is set like in the docs:

use Hyn\Tenancy\Abstracts\TenantModel;

class SomeTable extends TenantModel {}

Would this work?

Plytas commented 5 years ago

Just set it in config, not in the provider.

bkintanar commented 5 years ago

as per @Plytas I also set my default connection to system in the .env file, and just change the connection to tenant if app(Environment::class) resolves anything.

Plytas commented 5 years ago

@bkintanar as I understand it wouldn't let you use both system and tenant connections at the same time if you are just switching the connection instead of specifying them per model?

bkintanar commented 5 years ago

@Plytas I have set my .env file to system by default, but when the app boots, it checks if it is actually accessing a fqdn, and then I forcefully sets the connection to tenant with the code above.

xalunda commented 5 years ago

I've also set the TENANCY_DEFAULT_CONNECTION=system I don't have @bkintanar 's code to force tenant connection though. Seems like Hyn\Tenancy\Abstracts\TenantModel does its job.

Plytas commented 5 years ago

Good to hear. If your issue is solved, feel free to close it :)

xalunda commented 5 years ago

Thanks everyone! That was lighting fast and very effective. πŸ‘

bkintanar commented 5 years ago

Yeah, it was one of the solution most people used if they don't want to put the UsesTenantConnection trait.

One use case not to use the trait is that if you want to reuse your model in system and tenant connection

xalunda commented 5 years ago

One use case not to use the trait is that if you want to reuse your model in system and tenant connection

Yeah that's smart!