Multitenant
-----------

An application for making a Django application multitenant for Entr'ouvert
customers.

Based on https://django-tenant-schemas.readthedocs.org/

It is developed, tested and supported on Django 1.7, but it should work with
Django 1.6 + south.


Install
-------

See also : https://django-tenant-schemas.readthedocs.org/

Set the tenant model:

    TENANT_MODEL = 'multitenant.Tenant'

Where are tenants:

    TENANT_BASE = '/var/lib/<project>/tenants'

Add the middlewares for multitenant, they must be first:

    MIDDLEWARE = (
        'hobo.multitenant.middleware.TenantMiddleware',
    ) + MIDDLEWARE
    TENANT_SETTINGS_LOADERS = (
        'hobo.multitenant.settings_loaders.TemplateVars',
        'hobo.multitenant.settings_loaders.SettingsJSON',
        # 'hobo.multitenant.settings_loaders.Authentic',
    )

    # use TemplateVars with :
    TEMPLATE_CONTEXT_PROCESSORS = (
        'django.core.context_processors.request',
        'hobo.context_processors.template_vars',
    ) + TEMPLATE_CONTEXT_PROCESSORS


Define the shared applications:

    SHARED_APPS = (
        'tenant_schemas',
        'hobo.multitenant',
        # those are needed for the public apps to work
        # add also any application needed by the public app
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    )

    TENANT_APPS = INSTALLED_APPS

    INSTALLED_APPS = ('hobo.multitenant',
        'tenant_schemas') + INSTALLED_APPS

    # or, with Django 1.6 or older:
    # INSTALLED_APPS += ('tenant_schemas', 'hobo.multitenant')

Use multitenant database engine:

    DATABASES = {
        'default': {
            'ENGINE': 'tenant_schemas.postgresql_backend',
            'NAME': '<db_name>',
        },
    }
    DATABASE_ROUTERS = (
        'tenant_schemas.routers.TenantSyncRouter',
    )

    # With Django 1.6 or older, use multitenant south adapter:
    # SOUTH_DATABASE_ADAPTERS = {'default': 'south.db.postgresql_psycopg2'}


To multitenant-ify your cache backend:

    CACHES = {
        'default': {
            'BACKEND': 'hobo.multitenant.cache.TenantCache',
            # add a real Django cache backend, with its parameters if needed
            'REAL_BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

Add the multitenant filesystem template loader and configure where the
multitenant templates are located:

    TEMPLATE_LOADERS = (
        'hobo.multitenant.template_loader.FilesystemLoader',
    ) + TEMPLATE_LOADERS
    TENANT_TEMPLATE_DIRS = (TENANT_BASE,)



If a tenant doesn't exist, the tenant middleware raise a 404 error. If you
prefer to redirect to a specific site, use:
    TENANT_NOT_FOUND_REDIRECT_URL = 'http://www.example.net/'


Usage
-----

Create a tenant:
   manage.py create_tenant www.example.net
Migration of all tenants:
   manage.py migrate_schemas
Add a super user to tenant:
   manage.py tenant_command createsuperuser --domain www.example.net

Tenants are created in TENANT_BASE directory, for example :
    /var/lib/project/tenants/www.example.net/
               templates/  <-- override project templates
               static/     <-- to be handled by HTTP server
               media/
Each tenant is a PostgreSQL schema, named www_example_net


Mellon Integration
------------------

Sites can be incorporated in a SAML circle-of-trust by mean of Mellon; there
is a custom django-mellon adapter that will look for the first active identity
provider in the hobo.json and use that for authentication.

MELLON_ADAPTER = ('hobo.multitenant.mellon.MellonAdapter',)

In the service login view, the code path to mellon can thus dynamically be
chosen, using " if any(mellon.utils.get_idps()) ".


Haystack Integration
--------------------

At the present time support for Haystack exists only for the Whoosh engine,
with a single ("default") connection.

The index will be located in $tenant_dir/whoosh_index.

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'hobo.multitenant.haystack.WhooshEngine',
    }
}
