92 lines
3.5 KiB
Python
92 lines
3.5 KiB
Python
import json
|
|
import os
|
|
import urllib.parse
|
|
from shutil import rmtree
|
|
|
|
from django.conf import settings
|
|
from django.db import connection
|
|
from django.utils import timezone
|
|
from tenant_schemas.models import TenantMixin
|
|
from tenant_schemas.postgresql_backend.base import _check_schema_name
|
|
from tenant_schemas.utils import django_is_in_test_mode, get_public_schema_name, schema_exists
|
|
|
|
|
|
class Tenant(TenantMixin):
|
|
# default true, schema will be automatically created and synced when it is saved
|
|
auto_create_schema = False
|
|
__hobo_json = None
|
|
|
|
def save(self):
|
|
pass
|
|
|
|
def __unicode__(self):
|
|
return 'Tenant %s (%s)' % (self.domain_url, self.schema_name)
|
|
|
|
def __str__(self):
|
|
return 'Tenant %s (%s)' % (self.domain_url, self.schema_name)
|
|
|
|
@classmethod
|
|
def base(cls):
|
|
return settings.TENANT_BASE
|
|
|
|
def get_directory(self):
|
|
return os.path.join(self.base(), self.domain_url)
|
|
|
|
def get_hobo_json(self):
|
|
if not self.__hobo_json:
|
|
self.__hobo_json = json.load(open(os.path.join(self.get_directory(), 'hobo.json')))
|
|
return self.__hobo_json
|
|
|
|
def get_service(self):
|
|
for service in self.get_hobo_json()['services']:
|
|
if service.get('this'):
|
|
return service
|
|
|
|
def get_base_url(self):
|
|
if os.path.exists(os.path.join(self.get_directory(), 'base_url')):
|
|
return open(os.path.join(self.get_directory(), 'base_url')).read().strip().strip('/')
|
|
return 'https://%s' % self.domain_url
|
|
|
|
def build_absolute_uri(self, location):
|
|
return urllib.parse.urljoin(self.get_base_url(), location)
|
|
|
|
def create_schema(self, check_if_exists=False, sync_schema=True, verbosity=1, legacy_schema_name=None):
|
|
if not legacy_schema_name:
|
|
return super().create_schema(check_if_exists, sync_schema, verbosity)
|
|
# safety check
|
|
_check_schema_name(self.schema_name)
|
|
_check_schema_name(legacy_schema_name)
|
|
if check_if_exists and schema_exists(self.schema_name):
|
|
return False
|
|
if not schema_exists(legacy_schema_name):
|
|
return False
|
|
# rename schema
|
|
cursor = connection.cursor()
|
|
cursor.execute('ALTER SCHEMA %s RENAME TO %s' % (legacy_schema_name, self.schema_name))
|
|
connection.set_schema_to_public()
|
|
|
|
def delete(self, force_drop=False, *args, **kwargs):
|
|
"""
|
|
Deletes this row. Drops the tenant's schema if the attribute
|
|
auto_drop_schema set to True.
|
|
"""
|
|
if connection.schema_name not in (self.schema_name, get_public_schema_name()):
|
|
raise Exception(
|
|
"Can't delete tenant outside it's own schema or "
|
|
"the public schema. Current schema is %s." % connection.schema_name
|
|
)
|
|
if force_drop:
|
|
rmtree(self.get_directory())
|
|
else:
|
|
deletion_date = timezone.now().strftime('%Y%m%d_%H%M%S_%f')
|
|
os.rename(self.get_directory(), self.get_directory() + '.removed_%s.invalid' % deletion_date)
|
|
|
|
if schema_exists(self.schema_name) and (self.auto_drop_schema or force_drop):
|
|
cursor = connection.cursor()
|
|
cursor.execute('DROP SCHEMA %s CASCADE' % self.schema_name)
|
|
|
|
if schema_exists(self.schema_name) and (not self.auto_drop_schema and not force_drop):
|
|
cursor = connection.cursor()
|
|
schema_new_name = 'removed_%s_%s' % (deletion_date, self.schema_name)
|
|
cursor.execute('ALTER SCHEMA %s RENAME TO %s' % (self.schema_name, schema_new_name[:63]))
|