105 lines
3.9 KiB
Python
105 lines
3.9 KiB
Python
# hobo - portal to configure and deploy applications
|
|
# Copyright (C) 2015-2016 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import threading
|
|
import time
|
|
from importlib import import_module
|
|
|
|
from django.conf import UserSettingsHolder
|
|
from django.db import connection
|
|
|
|
|
|
def import_class(klass):
|
|
module, attr = klass.rsplit('.', 1)
|
|
return getattr(import_module(module), attr)
|
|
|
|
|
|
class TenantSettingsWrapper:
|
|
local = threading.local()
|
|
|
|
def __init__(self, default_settings):
|
|
self.__dict__['tenants_settings'] = {}
|
|
self.__dict__['default_settings'] = default_settings
|
|
|
|
def clear_tenants_settings(self):
|
|
self.__dict__['tenants_settings'] = {}
|
|
|
|
@property
|
|
def loaders(self):
|
|
loaders = getattr(self.default_settings, 'TENANT_SETTINGS_LOADERS', [])
|
|
for loader in loaders:
|
|
loader_class = import_class(loader)
|
|
yield loader_class()
|
|
|
|
def load_tenant_settings(self, tenant, tenant_settings, last_time):
|
|
"""Load tenant settings from loaders into tenant_settings object, only
|
|
if any of the loaders say it is more recent than last update time"""
|
|
update_time = time.time()
|
|
if last_time and update_time - last_time < 3:
|
|
return tenant_settings, last_time
|
|
new = False
|
|
for loader in self.loaders:
|
|
new_time = loader.get_new_time(tenant)
|
|
if (
|
|
(not new_time and last_time)
|
|
or (new_time and not last_time)
|
|
or (new_time and new_time > last_time)
|
|
):
|
|
new = True
|
|
break
|
|
|
|
if new:
|
|
tenant_settings = UserSettingsHolder(self.default_settings)
|
|
# something is new, call all loaders
|
|
for loader in self.loaders:
|
|
loader.update_settings(tenant_settings, tenant)
|
|
return tenant_settings, update_time
|
|
return tenant_settings, last_time
|
|
|
|
def get_tenant_settings(self, tenant):
|
|
"""Get last loaded settings for tenant, try to update it by loading
|
|
settings again is last loading time is less recent thant settings
|
|
data store. Compare with last modification time is done in the
|
|
load_tenant_settings() method.
|
|
"""
|
|
tenant_settings, last_time = self.tenants_settings.get(tenant.domain_url, (None, None))
|
|
if tenant_settings is None:
|
|
tenant_settings = UserSettingsHolder(self.default_settings)
|
|
tenant_settings, last_time = self.load_tenant_settings(tenant, tenant_settings, last_time)
|
|
self.tenants_settings[tenant.domain_url] = tenant_settings, last_time
|
|
return tenant_settings
|
|
|
|
def get_wrapped(self):
|
|
if getattr(self.local, 'in_get_wrapped', False):
|
|
return self.default_settings
|
|
try:
|
|
self.local.in_get_wrapped = True
|
|
tenant = connection.get_tenant()
|
|
if not hasattr(tenant, 'domain_url'):
|
|
return self.default_settings
|
|
return self.get_tenant_settings(tenant)
|
|
finally:
|
|
self.local.in_get_wrapped = False
|
|
|
|
def __getattr__(self, name):
|
|
return getattr(self.get_wrapped(), name)
|
|
|
|
def __setattr__(self, name, value):
|
|
setattr(self.get_wrapped(), name, value)
|
|
|
|
def __delattr__(self, name):
|
|
delattr(self.get_wrapped(), name)
|