mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 08:24:04 +00:00
Fix Travis, add docs for generating HTTPS certificates (#19)
This commit is contained in:
parent
0adbfee86e
commit
6bb18a2b95
8 changed files with 108 additions and 7 deletions
|
|
@ -1,12 +1,18 @@
|
||||||
language: php
|
language: php
|
||||||
php:
|
php:
|
||||||
- '7.1'
|
|
||||||
- '7.2'
|
- '7.2'
|
||||||
|
- '7.1'
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
services:
|
||||||
|
- redis-server
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- travis_retry composer install --no-interaction
|
- travis_retry composer install --no-interaction
|
||||||
|
|
||||||
|
|
|
||||||
38
README.md
38
README.md
|
|
@ -393,3 +393,41 @@ Tenant migrations are located in `database/migrations/tenant`, so you should mov
|
||||||
## Some tips
|
## Some tips
|
||||||
|
|
||||||
- If you create a tenant using the interactive console (`artisan tinker`) and use sqlite, you might need to change the database's permissions and/or ownership (`chmod`/`chown`) so that the web application can access it.
|
- If you create a tenant using the interactive console (`artisan tinker`) and use sqlite, you might need to change the database's permissions and/or ownership (`chmod`/`chown`) so that the web application can access it.
|
||||||
|
|
||||||
|
## HTTPS certificates
|
||||||
|
|
||||||
|
HTTPS certificates are very easy to deal with if you use the `yourclient1.yourapp.com`, `yourclient2.yourapp.com` model. You can use a wildcard HTTPS certificate.
|
||||||
|
|
||||||
|
If you use the model where second level domains are used, there are multiple ways you can solve this.
|
||||||
|
|
||||||
|
This guide focuses on nginx.
|
||||||
|
|
||||||
|
### 1. Use nginx with the lua module
|
||||||
|
|
||||||
|
Specifically, you're interested in the [`ssl_certificate_by_lua_block`](https://github.com/openresty/lua-nginx-module#ssl_certificate_by_lua_block) directive. Nginx doesn't support using variables such as the hostname in the `ssl_certificate` directive, which is why the lua module is needed.
|
||||||
|
|
||||||
|
This approach lets you use one server block for all tenants.
|
||||||
|
|
||||||
|
### 2. Add a simple server block for each tenant
|
||||||
|
|
||||||
|
You can store most of your config in a file, such as `/etc/nginx/includes/tenant`, and include this file into tenant server blocks.
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
include includes/tenant;
|
||||||
|
server_name foo.bar;
|
||||||
|
# ssl_certificate /etc/foo/...;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generating certificates
|
||||||
|
|
||||||
|
You can generate a certificate using certbot. If you use the `--nginx` flag, you will need to run certbot as root. If you use the `--webroot` flag, you only need the user that runs it to have write access to the webroot directory (or perhaps webroot/.well-known is enough) and some certbot files (you can specify these using --work-dir, --config-dir and --logs-dir).
|
||||||
|
|
||||||
|
Creating this config dynamically from PHP is not easy, but is probably feasible. Giving `www-data` write access to `/etc/nginx/sites-available/tenants.conf` should work.
|
||||||
|
|
||||||
|
However, you still need to reload nginx configuration to apply the changes to configuration. This is problematic and I'm not sure if there is a simple and secure way to do this from PHP.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
If you run the tests of this package, please make sure you don't store anything in Redis @ 127.0.0.1:6379 db#14. The contents of this database are flushed everytime the tests are run.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,10 @@
|
||||||
</testsuites>
|
</testsuites>
|
||||||
<filter>
|
<filter>
|
||||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||||
<directory suffix=".php">./app</directory>
|
<directory suffix=".php">./src</directory>
|
||||||
|
<exclude>
|
||||||
|
<file>./src/routes.php</file>
|
||||||
|
</exclude>
|
||||||
</whitelist>
|
</whitelist>
|
||||||
</filter>
|
</filter>
|
||||||
<php>
|
<php>
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,11 @@ class DatabaseManager
|
||||||
return DB::statement("CREATE DATABASE `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
return DB::statement("CREATE DATABASE `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
// todo: delete database. similar to create()
|
||||||
|
}
|
||||||
|
|
||||||
public function getDriver(): ?string
|
public function getDriver(): ?string
|
||||||
{
|
{
|
||||||
return config("database.connections.tenant.driver");
|
return config("database.connections.tenant.driver");
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Stancl\Tenancy\Commands\TenantList;
|
use Stancl\Tenancy\Commands\TenantList;
|
||||||
use Stancl\Tenancy\Interfaces\StorageDriver;
|
use Stancl\Tenancy\Interfaces\StorageDriver;
|
||||||
|
use Stancl\Tenancy\Interfaces\ServerConfigManager;
|
||||||
use Stancl\Tenancy\StorageDrivers\RedisStorageDriver;
|
use Stancl\Tenancy\StorageDrivers\RedisStorageDriver;
|
||||||
|
|
||||||
class TenancyServiceProvider extends ServiceProvider
|
class TenancyServiceProvider extends ServiceProvider
|
||||||
|
|
@ -54,6 +55,7 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
$this->mergeConfigFrom(__DIR__ . '/config/tenancy.php', 'tenancy');
|
$this->mergeConfigFrom(__DIR__ . '/config/tenancy.php', 'tenancy');
|
||||||
|
|
||||||
$this->app->bind(StorageDriver::class, $this->app['config']['tenancy.storage_driver']);
|
$this->app->bind(StorageDriver::class, $this->app['config']['tenancy.storage_driver']);
|
||||||
|
$this->app->bind(ServerConfigManager::class, $this->app['config']['tenancy.server.manager']);
|
||||||
$this->app->singleton(DatabaseManager::class);
|
$this->app->singleton(DatabaseManager::class);
|
||||||
$this->app->singleton(TenantManager::class, function ($app) {
|
$this->app->singleton(TenantManager::class, function ($app) {
|
||||||
return new TenantManager($app, $app[StorageDriver::class], $app[DatabaseManager::class]);
|
return new TenantManager($app, $app[StorageDriver::class], $app[DatabaseManager::class]);
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace Stancl\Tenancy;
|
namespace Stancl\Tenancy;
|
||||||
|
|
||||||
use Stancl\Tenancy\BootstrapsTenancy;
|
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
use Stancl\Tenancy\Interfaces\StorageDriver;
|
use Stancl\Tenancy\Interfaces\StorageDriver;
|
||||||
|
use Stancl\Tenancy\Traits\BootstrapsTenancy;
|
||||||
|
|
||||||
class TenantManager
|
class TenantManager
|
||||||
{
|
{
|
||||||
|
|
@ -77,7 +77,7 @@ class TenantManager
|
||||||
throw new \Exception("Domain $domain is already occupied by tenant $id.");
|
throw new \Exception("Domain $domain is already occupied by tenant $id.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$tenant = $this->storage->createTenant($domain, \Uuid::generate(1, $domain));
|
$tenant = $this->storage->createTenant($domain, \Webpatser\Uuid\Uuid::generate(1, $domain));
|
||||||
$this->database->create($this->getDatabaseName($tenant));
|
$this->database->create($this->getDatabaseName($tenant));
|
||||||
|
|
||||||
return $tenant;
|
return $tenant;
|
||||||
|
|
@ -264,4 +264,19 @@ class TenantManager
|
||||||
|
|
||||||
return $this->put($this->put($key, $value));
|
return $this->put($this->put($key, $value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the identified tenant's attribute(s).
|
||||||
|
*
|
||||||
|
* @param string $attribute
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function __invoke($attribute)
|
||||||
|
{
|
||||||
|
if (is_null($attribute)) {
|
||||||
|
return $this->tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->tenant[(string) $attribute];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Stancl\Tenancy;
|
namespace Stancl\Tenancy\Traits;
|
||||||
|
|
||||||
|
use Stancl\Tenancy\CacheManager;
|
||||||
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
|
||||||
trait BootstrapsTenancy
|
trait BootstrapsTenancy
|
||||||
{
|
{
|
||||||
|
|
@ -21,7 +24,6 @@ trait BootstrapsTenancy
|
||||||
|
|
||||||
public function setPhpRedisPrefix($connections = ['default'])
|
public function setPhpRedisPrefix($connections = ['default'])
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
foreach ($connections as $connection) {
|
foreach ($connections as $connection) {
|
||||||
$prefix = config('tenancy.redis.prefix_base') . $this->tenant['uuid'];
|
$prefix = config('tenancy.redis.prefix_base') . $this->tenant['uuid'];
|
||||||
$client = Redis::connection($connection)->client();
|
$client = Redis::connection($connection)->client();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Tests;
|
namespace Stancl\Tenancy\Tests;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
|
||||||
class TestCase extends \Orchestra\Testbench\TestCase
|
class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,7 +15,35 @@ class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
//
|
Redis::connection('tenancy')->flushdb();
|
||||||
|
|
||||||
|
tenant()->create('localhost');
|
||||||
|
|
||||||
|
tenancy()->init('localhost');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define environment setup.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Foundation\Application $app
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function getEnvironmentSetUp($app)
|
||||||
|
{
|
||||||
|
$app['config']->set('database.redis.client', 'phpredis');
|
||||||
|
$app['config']->set('database.redis.tenancy', [
|
||||||
|
'host' => env('TENANCY_TEST_REDIS_HOST', '127.0.0.1'),
|
||||||
|
'password' => env('TENANCY_TEST_REDIS_PASSWORD', null),
|
||||||
|
'port' => env('TENANCY_TEST_REDIS_PORT', 6379),
|
||||||
|
// Use the #14 Redis database unless specified otherwise.
|
||||||
|
// Make sure you don't store anything in this db!
|
||||||
|
'database' => env('TENANCY_TEST_REDIS_DB', 14),
|
||||||
|
]);
|
||||||
|
$app['config']->set('tenancy.database', [
|
||||||
|
'based_on' => 'sqlite',
|
||||||
|
'prefix' => 'tenant',
|
||||||
|
'suffix' => '.sqlite',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getPackageProviders($app)
|
protected function getPackageProviders($app)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue