0đź‘Ť
- You should separate any reusable logic that can safely be applied to each website to a node module and you should host this yourself. For the views / custom features, those should be in their own repository. You can trigger pipelines on
commit
to automatically roll out continuous integration to specified servers on a repository-specific basis.
For #2, it’s more complex. One easy way is to make a new table called api_users
, for instance. This will have 3 columns, id
, tenant_id
(or whatever your unique “tenant identifier” is) and token
and expiry
, where tenant_id
is an FK to your tenants
table. The token should just be a unique, long string.
Now you should pass that string on the frontend with any of your API Reqests. something like;
{
headers: {
'X-Tenant-Token': getTenantToken()
}
}
Then in Laravel make new middleware for this:
php artisan make:middelware TenantValidityMiddleware
In the handle
function, determine we need some logic:
if ($token = request()->headers()->get('X-Tenant-Token')) {
app()->singleton(Tenant::class, function ($app) {
return Tenant::whereHas('api_users', function(Builder $query){
return $query->where('token', $token);
})->firstOrFail();
});
return $next($request);
}
abort(401, 'Unauthorized access');
Now any dependency injected Tenant $tenant
calls will automatically resolve your tenant for this API request.
Also, you can make sure that this is the case by adding:
session(['token' => $token]);
And you can add some safety to your container resolution logic in your AppServiceProvider:
$this->app->resolving(Tenant::class, function ($tenant, $app) {
if (!$tenant->token === session('token') || auth()->user()->isAdmin()) {
abort(401, 'Unauthorized access');
}
});
This will help make sure that there are no forgery’s going on during requests.
(the token property of tenant is resolved like this:
public function getTokenAttribute()
{
return $this->tokens()->first()->token;
}
And of course you need to define the token
relationship:
public function tokens(): HasOne
{
return $this->hasOne(ApiToken::class, 'api_users', 'tenant_id');
}