Projet

Général

Profil

Télécharger (4,68 ko) Statistiques
| Branche: | Tag: | Révision:

root / entrouvert / djommon / multitenant / middleware.py @ ec0613c1

1
import os
2
import json
3

    
4
from django.conf import settings, UserSettingsHolder
5

    
6
from tenant_schemas.middleware import TenantMiddleware
7

    
8
SENTINEL = object()
9

    
10
class EOTenantMiddleware(TenantMiddleware):
11
    def __init__(self, *args, **kwargs):
12
        self.wrapped = settings._wrapped
13

    
14
    def process_request(self, request):
15
        super(EOTenantMiddleware, self).process_request(request)
16
        override = UserSettingsHolder(self.wrapped)
17
        for client_settings in request.tenant.clientsetting_set.all():
18
            setattr(override, client_settings.name, client_settings.json)
19
        settings._wrapped = override
20

    
21
    def process_response(self, request, response):
22
        settings._wrapped = self.wrapped
23
        return response
24

    
25
class TenantSettingBaseMiddleware(object):
26
    '''Base middleware classe for loading settings based on tenants
27

    
28
       Child classes MUST override the load_tenant_settings() method.
29
    '''
30
    def __init__(self, *args, **kwargs):
31
        self.tenants_settings = {}
32

    
33
    def get_tenant_settings(self, wrapped, tenant):
34
        '''Get last loaded settings for tenant, try to update it by loading
35
           settings again is last loading time is less recent thant settings data
36
           store. Compare with last modification time is done in the
37
           load_tenant_settings() method.
38
        '''
39
        tenant_settings, last_time = self.tenants_settings.get(tenant.schema_name, (None,None))
40
        if tenant_settings is None:
41
            tenant_settings = UserSettingsHolder(wrapped)
42
        tenant_settings, last_time = self.load_tenant_settings(wrapped, tenant, tenant_settings, last_time)
43
        self.tenants_settings[tenant.schema_name] = tenant_settings, last_time
44
        return tenant_settings
45

    
46
    def load_tenant_settings(self, wrapped, tenant, tenant_settings, last_time):
47
        '''Load tenant settings into tenant_settings object, eventually skip if
48
           last_time is more recent than last update time for settings and return
49
           the new value for tenant_settings and last_time'''
50
        raise NotImplemented
51

    
52
    def process_request(self, request):
53
        if not hasattr(request, '_old_settings_wrapped'):
54
            request._old_settings_wrapped = []
55
        request._old_settings_wrapped.append(settings._wrapped)
56
        settings._wrapped = self.get_tenant_settings(settings._wrapped, request.tenant)
57

    
58
    def process_response(self, request, response):
59
        if hasattr(request, '_old_settings_wrapped') and request._old_settings_wrapped:
60
            settings._wrapped = request._old_settings_wrapped.pop()
61
        return response
62

    
63

    
64
class FileBasedTenantSettingBaseMiddleware(TenantSettingBaseMiddleware):
65
    FILENAME = None
66

    
67
    def load_tenant_settings(self, wrapped, tenant, tenant_settings, last_time):
68
        path = os.path.join(settings.TENANT_BASE, tenant.schema_name, self.FILENAME)
69
        try:
70
            new_time = os.stat(path).st_mtime
71
        except OSError:
72
            # file was removed
73
            if not last_time is None:
74
                return UserSettingsHolder(wrapped), None
75
        else:
76
            if last_time is None or new_time >= last_time:
77
                # file is new
78
                tenant_settings = UserSettingsHolder(wrapped)
79
                self.load_file(tenant_settings, path)
80
                return tenant_settings, new_time
81
        # nothing has changed
82
        return tenant_settings, last_time
83

    
84

    
85
class JSONSettingsMiddleware(FileBasedTenantSettingBaseMiddleware):
86
    '''Load settings from a JSON file whose path is given by:
87

    
88
            os.path.join(settings.TENANT_BASE % schema_name, 'settings.json')
89

    
90
       The JSON file must be a dictionnary whose key/value will override
91
       current settings.
92
    '''
93
    FILENAME = 'settings.json'
94

    
95
    def load_file(sef, tenant_settings, path):
96
        with file(path) as f:
97
            json_settings = json.load(f)
98
            for key in json_settings:
99
                setattr(tenant_settings, key, json_settings[key])
100

    
101

    
102
class DictAdapter(dict):
103
    '''Give dict interface to plain objects'''
104
    def __init__(self, wrapped):
105
        self.wrapped = wrapped
106

    
107
    def __setitem__(self, key, value):
108
        setattr(self.wrapped, key, value)
109

    
110
    def __getitem__(self, key):
111
        try:
112
            return getattr(self.wrapped, key)
113
        except AttributeError:
114
            raise KeyError
115

    
116

    
117
class PythonSettingsMiddleware(JSONSettingsMiddleware):
118
    '''Load settings from a file whose path is given by:
119

    
120
            os.path.join(settings.TENANT_BASE % schema_name, 'settings.py')
121

    
122
       The file is executed in the same context as the classic settings file
123
       using execfile.
124
    '''
125
    FILENAME = 'settings.py'
126

    
127
    def load_file(self, tenant_settings, path):
128
        execfile(path, DictAdapter(tenant_settings))
(3-3/7)