1# -*- coding: utf-8 -*-
2from __future__ import absolute_import
3
4import logging
5import os
6
7from django.conf import settings
8from django.core.exceptions import ImproperlyConfigured
9from django.core.files.storage import get_storage_class
10
11from .utils.loader import load_object
12from .utils.recursive_dictionary import RecursiveDictionaryWithExcludes
13
14
15logger = logging.getLogger(__name__)
16
17# FILER_IMAGE_MODEL setting is used to swap Image model.
18# If such global setting does not exist, it will be created at this point (with default model name).
19# This is needed especially when using this setting in migrations.
20if not hasattr(settings, 'FILER_IMAGE_MODEL'):
21    setattr(settings, 'FILER_IMAGE_MODEL', 'filer.Image')
22FILER_IMAGE_MODEL = settings.FILER_IMAGE_MODEL
23
24FILER_DEBUG = getattr(settings, 'FILER_DEBUG', False)  # When True makes
25FILER_SUBJECT_LOCATION_IMAGE_DEBUG = getattr(settings, 'FILER_SUBJECT_LOCATION_IMAGE_DEBUG', False)
26FILER_WHITESPACE_COLOR = getattr(settings, 'FILER_WHITESPACE_COLOR', '#FFFFFF')
27
28FILER_0_8_COMPATIBILITY_MODE = getattr(settings, 'FILER_0_8_COMPATIBILITY_MODE', False)
29
30FILER_ENABLE_LOGGING = getattr(settings, 'FILER_ENABLE_LOGGING', False)
31if FILER_ENABLE_LOGGING:
32    FILER_ENABLE_LOGGING = (
33        FILER_ENABLE_LOGGING and (getattr(settings, 'LOGGING')
34                             and ('' in settings.LOGGING['loggers']
35                             or 'filer' in settings.LOGGING['loggers'])))
36
37FILER_ENABLE_PERMISSIONS = getattr(settings, 'FILER_ENABLE_PERMISSIONS', False)
38FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS = getattr(settings, 'FILER_ALLOW_REGULAR_USERS_TO_ADD_ROOT_FOLDERS', False)
39FILER_IS_PUBLIC_DEFAULT = getattr(settings, 'FILER_IS_PUBLIC_DEFAULT', True)
40
41FILER_PAGINATE_BY = getattr(settings, 'FILER_PAGINATE_BY', 20)
42
43_ICON_SIZES = getattr(settings, 'FILER_ADMIN_ICON_SIZES', ('16', '32', '48', '64'))
44if not _ICON_SIZES:
45    raise ImproperlyConfigured('Please, configure FILER_ADMIN_ICON_SIZES')
46# Reliably sort by integer value, but keep icon size as string.
47# (There is some code in the wild that depends on this being strings.)
48FILER_ADMIN_ICON_SIZES = [str(i) for i in sorted([int(s) for s in _ICON_SIZES])]
49
50# Filer admin templates have specific icon sizes hardcoded: 32 and 48.
51_ESSENTIAL_ICON_SIZES = ('32', '48')
52if not all(x in FILER_ADMIN_ICON_SIZES for x in _ESSENTIAL_ICON_SIZES):
53    logger.warn(
54        "FILER_ADMIN_ICON_SIZES has not all of the essential icon sizes "
55        "listed: {}. Some icons might be missing in admin templates.".format(
56            _ESSENTIAL_ICON_SIZES))
57
58# This is an ordered iterable that describes a list of
59# classes that I should check for when adding files
60FILER_FILE_MODELS = getattr(
61    settings, 'FILER_FILE_MODELS',
62    (FILER_IMAGE_MODEL, 'filer.File'))
63
64DEFAULT_FILE_STORAGE = getattr(settings, 'DEFAULT_FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')
65
66MINIMAL_FILER_STORAGES = {
67    'public': {
68        'main': {
69            'ENGINE': None,
70            'OPTIONS': {},
71        },
72        'thumbnails': {
73            'ENGINE': None,
74            'OPTIONS': {},
75        }
76    },
77    'private': {
78        'main': {
79            'ENGINE': None,
80            'OPTIONS': {},
81        },
82        'thumbnails': {
83            'ENGINE': None,
84            'OPTIONS': {},
85        },
86    },
87}
88
89
90DEFAULT_FILER_STORAGES = {
91    'public': {
92        'main': {
93            'ENGINE': DEFAULT_FILE_STORAGE,
94            'OPTIONS': {},
95            'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
96            'UPLOAD_TO_PREFIX': 'filer_public',
97        },
98        'thumbnails': {
99            'ENGINE': DEFAULT_FILE_STORAGE,
100            'OPTIONS': {},
101            'THUMBNAIL_OPTIONS': {
102                'base_dir': 'filer_public_thumbnails',
103            },
104        },
105    },
106    'private': {
107        'main': {
108            'ENGINE': 'filer.storage.PrivateFileSystemStorage',
109            'OPTIONS': {
110                'location': os.path.abspath(os.path.join(settings.MEDIA_ROOT, '../smedia/filer_private')),
111                'base_url': '/smedia/filer_private/',
112            },
113            'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
114            'UPLOAD_TO_PREFIX': '',
115        },
116        'thumbnails': {
117            'ENGINE': 'filer.storage.PrivateFileSystemStorage',
118            'OPTIONS': {
119                'location': os.path.abspath(os.path.join(settings.MEDIA_ROOT, '../smedia/filer_private_thumbnails')),
120                'base_url': '/smedia/filer_private_thumbnails/',
121            },
122            'THUMBNAIL_OPTIONS': {},
123        },
124    },
125}
126
127MINIMAL_FILER_SERVERS = {
128    'private': {
129        'main': {
130            'ENGINE': None,
131            'OPTIONS': {},
132        },
133        'thumbnails': {
134            'ENGINE': None,
135            'OPTIONS': {},
136        },
137    },
138}
139
140DEFAULT_FILER_SERVERS = {
141    'private': {
142        'main': {
143            'ENGINE': 'filer.server.backends.default.DefaultServer',
144            'OPTIONS': {},
145        },
146        'thumbnails': {
147            'ENGINE': 'filer.server.backends.default.DefaultServer',
148            'OPTIONS': {},
149        },
150    },
151}
152
153FILER_STORAGES = RecursiveDictionaryWithExcludes(MINIMAL_FILER_STORAGES, rec_excluded_keys=('OPTIONS', 'THUMBNAIL_OPTIONS'))
154if FILER_0_8_COMPATIBILITY_MODE:
155    user_filer_storages = {
156        'public': {
157            'main': {
158                'ENGINE': DEFAULT_FILE_STORAGE,
159                'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
160                'UPLOAD_TO_PREFIX': getattr(settings, 'FILER_PUBLICMEDIA_PREFIX', 'filer_public'),
161            },
162            'thumbnails': {
163                'ENGINE': DEFAULT_FILE_STORAGE,
164                'OPTIONS': {},
165                'THUMBNAIL_OPTIONS': {
166                    'base_dir': 'filer_public_thumbnails',
167                },
168            },
169        },
170        'private': {
171            'main': {
172                'ENGINE': DEFAULT_FILE_STORAGE,
173                'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
174                'UPLOAD_TO_PREFIX': getattr(settings, 'FILER_PRIVATEMEDIA_PREFIX', 'filer_private'),
175            },
176            'thumbnails': {
177                'ENGINE': DEFAULT_FILE_STORAGE,
178                'OPTIONS': {},
179                'THUMBNAIL_OPTIONS': {
180                    'base_dir': 'filer_private_thumbnails',
181                },
182            },
183        },
184    }
185else:
186    user_filer_storages = getattr(settings, 'FILER_STORAGES', {})
187
188FILER_STORAGES.rec_update(user_filer_storages)
189
190
191def update_storage_settings(user_settings, defaults, s, t):
192    if not user_settings[s][t]['ENGINE']:
193        user_settings[s][t]['ENGINE'] = defaults[s][t]['ENGINE']
194        user_settings[s][t]['OPTIONS'] = defaults[s][t]['OPTIONS']
195    if t == 'main':
196        if 'UPLOAD_TO' not in user_settings[s][t]:
197            user_settings[s][t]['UPLOAD_TO'] = defaults[s][t]['UPLOAD_TO']
198        if 'UPLOAD_TO_PREFIX' not in user_settings[s][t]:
199            user_settings[s][t]['UPLOAD_TO_PREFIX'] = defaults[s][t]['UPLOAD_TO_PREFIX']
200    if t == 'thumbnails':
201        if 'THUMBNAIL_OPTIONS' not in user_settings[s][t]:
202            user_settings[s][t]['THUMBNAIL_OPTIONS'] = defaults[s][t]['THUMBNAIL_OPTIONS']
203    return user_settings
204
205
206update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'public', 'main')
207update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'public', 'thumbnails')
208update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'private', 'main')
209update_storage_settings(FILER_STORAGES, DEFAULT_FILER_STORAGES, 'private', 'thumbnails')
210
211FILER_SERVERS = RecursiveDictionaryWithExcludes(MINIMAL_FILER_SERVERS, rec_excluded_keys=('OPTIONS',))
212FILER_SERVERS.rec_update(getattr(settings, 'FILER_SERVERS', {}))
213
214
215def update_server_settings(settings, defaults, s, t):
216    if not settings[s][t]['ENGINE']:
217        settings[s][t]['ENGINE'] = defaults[s][t]['ENGINE']
218        settings[s][t]['OPTIONS'] = defaults[s][t]['OPTIONS']
219    return settings
220
221
222update_server_settings(FILER_SERVERS, DEFAULT_FILER_SERVERS, 'private', 'main')
223update_server_settings(FILER_SERVERS, DEFAULT_FILER_SERVERS, 'private', 'thumbnails')
224
225
226# Public media (media accessible without any permission checks)
227FILER_PUBLICMEDIA_STORAGE = get_storage_class(FILER_STORAGES['public']['main']['ENGINE'])(**FILER_STORAGES['public']['main']['OPTIONS'])
228FILER_PUBLICMEDIA_UPLOAD_TO = load_object(FILER_STORAGES['public']['main']['UPLOAD_TO'])
229if 'UPLOAD_TO_PREFIX' in FILER_STORAGES['public']['main']:
230    FILER_PUBLICMEDIA_UPLOAD_TO = load_object('filer.utils.generate_filename.prefixed_factory')(FILER_PUBLICMEDIA_UPLOAD_TO, FILER_STORAGES['public']['main']['UPLOAD_TO_PREFIX'])
231FILER_PUBLICMEDIA_THUMBNAIL_STORAGE = get_storage_class(FILER_STORAGES['public']['thumbnails']['ENGINE'])(**FILER_STORAGES['public']['thumbnails']['OPTIONS'])
232FILER_PUBLICMEDIA_THUMBNAIL_OPTIONS = FILER_STORAGES['public']['thumbnails']['THUMBNAIL_OPTIONS']
233
234
235# Private media (media accessible through permissions checks)
236FILER_PRIVATEMEDIA_STORAGE = get_storage_class(FILER_STORAGES['private']['main']['ENGINE'])(**FILER_STORAGES['private']['main']['OPTIONS'])
237FILER_PRIVATEMEDIA_UPLOAD_TO = load_object(FILER_STORAGES['private']['main']['UPLOAD_TO'])
238if 'UPLOAD_TO_PREFIX' in FILER_STORAGES['private']['main']:
239    FILER_PRIVATEMEDIA_UPLOAD_TO = load_object('filer.utils.generate_filename.prefixed_factory')(FILER_PRIVATEMEDIA_UPLOAD_TO, FILER_STORAGES['private']['main']['UPLOAD_TO_PREFIX'])
240FILER_PRIVATEMEDIA_THUMBNAIL_STORAGE = get_storage_class(FILER_STORAGES['private']['thumbnails']['ENGINE'])(**FILER_STORAGES['private']['thumbnails']['OPTIONS'])
241FILER_PRIVATEMEDIA_THUMBNAIL_OPTIONS = FILER_STORAGES['private']['thumbnails']['THUMBNAIL_OPTIONS']
242FILER_PRIVATEMEDIA_SERVER = load_object(FILER_SERVERS['private']['main']['ENGINE'])(**FILER_SERVERS['private']['main']['OPTIONS'])
243FILER_PRIVATEMEDIA_THUMBNAIL_SERVER = load_object(FILER_SERVERS['private']['thumbnails']['ENGINE'])(**FILER_SERVERS['private']['thumbnails']['OPTIONS'])
244
245# By default limit number of simultaneous uploads if we are using SQLite
246if settings.DATABASES['default']['ENGINE'].endswith('sqlite3'):
247    _uploader_connections = 1
248else:
249    _uploader_connections = 3
250FILER_UPLOADER_CONNECTIONS = getattr(
251    settings, 'FILER_UPLOADER_CONNECTIONS', _uploader_connections)
252
253FILER_DUMP_PAYLOAD = getattr(settings, 'FILER_DUMP_PAYLOAD', False)  # Whether the filer shall dump the files payload
254
255FILER_CANONICAL_URL = getattr(settings, 'FILER_CANONICAL_URL', 'canonical/')
256