Giter Site home page Giter Site logo

hyn-nova's Introduction

Tenancy logo Tenancy Ecosystem (for Laravel)

Enabling awesome Software as a Service with the Laravel framework.

This is the successor of hyn/multi-tenant.

Feel free to show support by starring the project following progress via twitter and backing its development over at OpenCollective or GitHub Sponsors.

Tests Code Style Code Coverage Subsplit

Before you start, we highly recommend you to read the extensive online documentation.

Installation

To give this package a spin, install all components at once:

$ composer require tenancy/tenancy

Otherwise make sure to selectively install the components you need and at least the framework:

$ composer require tenancy/framework

After that you'll need to decide on and configure:

Contributions

This repository is used for developing all tenancy packages.

Contributors need to use this repository for implementing code. All other repositories are READ-ONLY and overwritten on each subsplit push.

Please read our Governance documentation in case you'd like to get involved.

Local Testing

Testing the ecosystem locally is possible when:

  • You have Docker (and docker-compose) installed
  • You have Bash installed

When you have those requirements, you can simply run ./test in order to run the test in Docker containers. By default they will run the most recent versions of all our dependencies

hyn-nova's People

Contributors

bkintanar avatar luceos avatar plytas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hyn-nova's Issues

Can't force Nova to use system database

It's trying to access [tenant] database by default. When trying to login through web or

$ php artisan nova:user
> Database [tenant] not configured

I tried various things including adding a middleware to Nova forcing the database.default config to system, but I didn't have any luck.

Milestone items

Do you have milestone here? Maybe we can help to develop this nova package.

Thanks.

Tenant switcher

I don't really have the time to submit a proper PR, but here is what it takes to make a tenant switcher for Nova.

My use cas is the following:

I needed that:

  • Nova only shows "system" resources when viewing the admin tenant
  • Nova only shows "tenant" resources when virtually switched to a client tenant

New Middleware

namespace App\Nova\Middleware;

use Closure;
use Domain\CustomerAccounts\Models\Website;
use Hyn\Tenancy\Environment;

class TenantSwitcherMiddleware
{

    /** @var \Hyn\Tenancy\Environment */
    private $environment;

    public function __construct(Environment $environment)
    {
        $this->environment = $environment;
    }

    public function handle($request, Closure $next)
    {
        $currentTenant = Website::find(session()->get('nova.tenant', 0))
                         ?? Website::whereUuid(Website::ADMIN_TENANT_UUID)->first();

        $this->environment->tenant($currentTenant);
        $this->environment->hostname($currentTenant->hostname);
        
        config()->set('tenancy.hostname.auto-identification', false);

        return $next($request);
    }
}

New view for the switcher dropdown

Create a new file resources/views/vendor/nova/partials/tenant-switcher.blade.php

@php($currentWebsite = app(Hyn\Tenancy\Environment::class)->website())
@php($websites =  Domain\CustomerAccounts\Models\Website::get())

<dropdown-trigger class="h-9 flex items-center" slot-scope="{toggle}" :handle-click="toggle">
    <span class="text-90">
        @if($currentWebsite->is_admin_tenant)
            Switch tenant...
        @else
            {{-- We have an extra customer table for billing, could use hostname->first()->fqdn instead of customer->name --}}
            {{ $currentWebsite->customer->name ?? $currentWebsite->uuid }}
        @endif
    </span>
</dropdown-trigger>

<dropdown-menu slot="menu" width="200" direction="rtl">
    <ul class="list-reset">
        <li>
            <a href="{{ route('web.nova.tenant.switch') }}" class="block no-underline text-90 hover:bg-30 p-3">
                Admin tenant
            </a>
        </li>
        @foreach($websites->reject->is_admin_tenant as $website)
        <li>
            <a href="{{ route('web.nova.tenant.switch', $website) }}" class="block no-underline text-90 hover:bg-30 p-3">
                {{ $website->customer->name ?? $website->uuid }} 
            </a>
        </li>
        @endforeach
    </ul>
</dropdown-menu>

New controller to make the switch

namespace App\Nova\Web\Controllers;

use App\Shared\Http\Controllers\Controller;
use Domain\CustomerAccounts\Models\Website;
use Illuminate\Http\Request;

class TenantController extends Controller
{
    public function switchTo(Request $request, ?Website $website = null)
    {
        session()->put('nova.tenant', $website->id ?? 0);
        return \redirect()->back();
    }
}

New route to that controller

You should add that route so that it is only accessible to the admin middleware. We have automatted

Route::domain('admin.' . env('APP_DOMAIN'))->prefix('/nova')->group(function () {
    Route::get('/switch-tenant/{website?}')->name('tenant.switch')->uses([TenantController::class, 'switchTo']);
});

Nova configuration

Add our manual tenant switcher middleware as last item in the nova configuration entry: nova.middleware

Nova layout

We need to change the Nova default layout in order to include our tenant switcher dropdown in the top bar.

Copy vendor/laravel/nova/resources/views/layout.blade.php to resources/views/vendor/nova/layout.blade.php

Then you can replace:

<dropdown class="ml-auto h-9 flex items-center dropdown-right">
    @include('nova::partials.user')
</dropdown>

with

<div class="ml-auto flex">
    <dropdown class="h-9 items-center dropdown-right">
        @include('nova::partials.tenant-switcher')
    </dropdown>

    <dropdown class="h-9 ml-6 items-center dropdown-right">
        @include('nova::partials.user')
    </dropdown>
</div>

Tenant aware resources

Here is how you can hide resources when switched to a tenant or to the system tenant in Nova using #5

Some traits

trait TenantAwareResource
{
    public static function availableForNavigation(Request $request)
    {
        $isTenantResource = static::$system === false;
        $isCustomerTenant = optional(app(Environment::class)->website())->is_admin_tenant !== true ?? false;

        return ($isTenantResource && $isCustomerTenant)
               || (!$isTenantResource && !$isCustomerTenant);
    }
}

trait IsSystemResource
{
    use TenantAwareResource;

    protected static $system = true;
}

trait IsTenantResource
{
    use TenantAwareResource;

    protected static $system = false;
}

Then you simply need to use the trait in your resources to show/hide them based on the context.

Creating of tenants is not working without the repository

The package requires that for instance website objects have to be send through the Website Repository create method in order for it to fire the appropriate events.

Sadly Nova uses the model directly and the documentation suggest using Model Observers instead, see https://nova.laravel.com/docs/1.0/resources/#resource-events

What has to be done is to write for each of our resources an observer and dispatch the required events used in the repository.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.