diff --git a/addons/aldryn-django-cms/addon.json b/addons/aldryn-django-cms/addon.json new file mode 100644 index 0000000..694440f --- /dev/null +++ b/addons/aldryn-django-cms/addon.json @@ -0,0 +1,6 @@ +{ + "installed-apps": [ + "filer.contrib.django_cms" + ], + "package-name": "aldryn-django-cms" +} \ No newline at end of file diff --git a/addons/aldryn-django-cms/aldryn_config.py b/addons/aldryn-django-cms/aldryn_config.py new file mode 100644 index 0000000..3fc7113 --- /dev/null +++ b/addons/aldryn-django-cms/aldryn_config.py @@ -0,0 +1,275 @@ +# -*- coding: utf-8 -*- +import json +import os + +from aldryn_client import forms + +SYSTEM_FIELD_WARNING = 'WARNING: this field is auto-written. Please do not change it here.' + + +class Form(forms.BaseForm): + permissions_enabled = forms.CheckboxField( + 'Enable permission checks', + required=False, + initial=True, + help_text=( + 'When set, provides new fields in each page\'s settings to assign ' + 'levels of access to particular users.' + ), + ) + cms_templates = forms.CharField( + 'CMS Templates', + required=True, + initial='[["default.html", "Default"]]', + help_text=( + 'A list, in JSON format, of django CMS templates available to the ' + 'project. Use double quotes for values. This list will be ' + 'overridden if the project supplies a CMS_TEMPLATES setting. See Manage templates in your django CMS project for more information.' + ), + ) + boilerplate_name = forms.CharField( + 'Boilerplate Name', + required=False, + initial='', + help_text=SYSTEM_FIELD_WARNING, + ) + cms_content_cache_duration = forms.NumberField( + 'Set Cache Duration for Content', + required=False, + initial=60, + help_text=( + 'Cache expiration (in seconds) for show_placeholder, page_url, ' + 'placeholder and static_placeholder template tags.' + ), + ) + cms_menus_cache_duration = forms.NumberField( + 'Set Cache Duration for Menus', + required=False, + initial=3600, + help_text='Cache expiration (in seconds) for the menu tree.', + ) + + def to_settings(self, data, settings): + from functools import partial + from django.core.urlresolvers import reverse_lazy + from aldryn_addons.utils import boolean_ish, djsenv + + env = partial(djsenv, settings=settings) + + # Need to detect if these settings are for Django 1.8+ + # Is there a better way? Can't import django to check version =( + is_django_18_or_later = ('TEMPLATES' in settings) + + # Core CMS stuff + settings['INSTALLED_APPS'].extend([ + 'cms', + # 'aldryn_django_cms' must be after 'cms', otherwise we get + # import time exceptions on other packages (e.g alryn-bootstrap3 + # returns: + # link_page = cms.models.fields.PageField( + # AttributeError: 'module' object has no attribute 'fields' + # ) + 'aldryn_django_cms', + 'menus', + 'sekizai', + 'treebeard', + ]) + + # TODO: break out this stuff into other addons + settings['INSTALLED_APPS'].extend([ + 'parler', + ]) + settings['INSTALLED_APPS'].insert( + settings['INSTALLED_APPS'].index('django.contrib.admin'), + 'djangocms_admin_style', + ) + + if is_django_18_or_later: + settings['TEMPLATES'][0]['OPTIONS']['context_processors'].extend([ + 'sekizai.context_processors.sekizai', + 'cms.context_processors.cms_settings', + ]) + else: + settings['TEMPLATE_CONTEXT_PROCESSORS'].extend([ + 'sekizai.context_processors.sekizai', + 'cms.context_processors.cms_settings', + ]) + + settings['MIDDLEWARE_CLASSES'].extend([ + 'cms.middleware.user.CurrentUserMiddleware', + 'cms.middleware.page.CurrentPageMiddleware', + 'cms.middleware.toolbar.ToolbarMiddleware', + 'cms.middleware.language.LanguageCookieMiddleware', + ]) + settings['MIDDLEWARE_CLASSES'].insert(0, 'cms.middleware.utils.ApphookReloadMiddleware',) + + settings['ADDON_URLS_I18N_LAST'] = 'cms.urls' + + settings['CMS_PERMISSION'] = data['permissions_enabled'] + + cache_durations = settings.setdefault('CMS_CACHE_DURATIONS', { + 'content': 60, + 'menus': 60 * 60, + 'permissions': 60 * 60, + }) + + if data['cms_content_cache_duration']: + cache_durations['content'] = data['cms_content_cache_duration'] + + if data['cms_menus_cache_duration']: + cache_durations['menus'] = data['cms_menus_cache_duration'] + + old_cms_templates_json = os.path.join(settings['BASE_DIR'], 'cms_templates.json') + + if os.path.exists(old_cms_templates_json): + # Backwards compatibility with v2 + with open(old_cms_templates_json) as fobj: + templates = json.load(fobj) + else: + templates= settings.get('CMS_TEMPLATES', json.loads(data['cms_templates'])) + + settings['CMS_TEMPLATES'] = templates + + # languages + language_codes = [code for code, lang in settings['LANGUAGES']] + settings['CMS_LANGUAGES'] = { + 'default': { + 'fallbacks': [fbcode for fbcode in language_codes], + 'redirect_on_fallback': True, + 'public': True, + 'hide_untranslated': False, + }, + 1: [ + { + 'code': code, + 'name': settings['ALL_LANGUAGES_DICT'][code], + 'fallbacks': [fbcode for fbcode in language_codes if fbcode != code], + 'public': True + } for code in language_codes + ] + } + + settings['PARLER_LANGUAGES'] = {} + + for site_id, languages in settings['CMS_LANGUAGES'].items(): + if isinstance(site_id, int): + langs = [ + { + 'code': lang['code'], + 'fallbacks': [fbcode for fbcode in language_codes if fbcode != lang['code']] + } for lang in languages + ] + settings['PARLER_LANGUAGES'].update({site_id: langs}) + + parler_defaults = {'fallback': settings['LANGUAGE_CODE']} + + for k, v in settings['CMS_LANGUAGES'].get('default', {}).items(): + if k in ['hide_untranslated', ]: + parler_defaults.update({k: v}) + + settings['PARLER_LANGUAGES'].update({'default': parler_defaults}) + + # aldryn-boilerplates and aldryn-snake + + # FIXME: Make ALDRYN_BOILERPLATE_NAME a configurable parameter + + settings['ALDRYN_BOILERPLATE_NAME'] = env( + 'ALDRYN_BOILERPLATE_NAME', + data.get('boilerplate_name', 'legacy'), + ) + settings['INSTALLED_APPS'].append('aldryn_boilerplates') + + if is_django_18_or_later: + TEMPLATE_CONTEXT_PROCESSORS = settings['TEMPLATES'][0]['OPTIONS']['context_processors'] + TEMPLATE_LOADERS = settings['TEMPLATES'][0]['OPTIONS']['loaders'] + else: + TEMPLATE_CONTEXT_PROCESSORS = settings['TEMPLATE_CONTEXT_PROCESSORS'] + TEMPLATE_LOADERS = settings['TEMPLATE_LOADERS'] + TEMPLATE_CONTEXT_PROCESSORS.extend([ + 'aldryn_boilerplates.context_processors.boilerplate', + 'aldryn_snake.template_api.template_processor', + ]) + TEMPLATE_LOADERS.insert( + TEMPLATE_LOADERS.index( + 'django.template.loaders.app_directories.Loader'), + 'aldryn_boilerplates.template_loaders.AppDirectoriesLoader' + ) + + settings['STATICFILES_FINDERS'].insert( + settings['STATICFILES_FINDERS'].index('django.contrib.staticfiles.finders.AppDirectoriesFinder'), + 'aldryn_boilerplates.staticfile_finders.AppDirectoriesFinder', + ) + + # django sitemap support + settings['INSTALLED_APPS'].append('django.contrib.sitemaps') + + # django-compressor + settings['INSTALLED_APPS'].append('compressor') + settings['STATICFILES_FINDERS'].append('compressor.finders.CompressorFinder') + # Disable django-comporessor for now. It does not work with the current + # setup. The cache is shared, which holds the manifest. But the + # compressed files reside in the docker container, which can go away at + # any time. + # Working solutions could be: + # 1) use pre-compression + # (https://django-compressor.readthedocs.org/en/latest/usage/#pre-compression) + # at docker image build time. + # 2) Use shared storage and save the manifest with the generated files. + # Although that could be a problem if different versions of the same + # app compete for the manifest file. + + # We're keeping compressor in INSTALLED_APPS for now, so that templates + # in existing projects don't break. + settings['COMPRESS_ENABLED'] = env('COMPRESS_ENABLED', False) + + if settings['COMPRESS_ENABLED']: + # Set far-future expiration headers for django-compressor + # generated files. + settings.setdefault('STATIC_HEADERS', []).insert(0, ( + r'{}/.*'.format(settings.get('COMPRESS_OUTPUT_DIR', 'CACHE')), + { + 'Cache-Control': 'public, max-age={}'.format(86400 * 365), + }, + )) + + # django-robots + settings['INSTALLED_APPS'].append('robots') + + settings['MIGRATION_COMMANDS'].append( + 'python manage.py cms fix-tree' + ) + + # default plugins + settings['INSTALLED_APPS'].extend([ + # required by aldryn-forms + 'captcha', + ]) + + # select2 (required by djangocms_link plugin) + settings['INSTALLED_APPS'].extend([ + 'django_select2', + ]) + + settings['ADDON_URLS'].append('aldryn_django_cms.urls') + settings['ADDON_URLS_I18N'].append('aldryn_django_cms.urls_i18n') + + if 'ALDRYN_SSO_LOGIN_WHITE_LIST' in settings: + # stage sso enabled + # add internal endpoints that do not require authentication + settings['ALDRYN_SSO_LOGIN_WHITE_LIST'].append(reverse_lazy('cms-check-uninstall')) + # this is an internal django-cms url + # which gets called when a user logs out from toolbar + settings['ALDRYN_SSO_LOGIN_WHITE_LIST'].append(reverse_lazy('admin:cms_page_resolve')) + + # Prevent injecting random comments to counter BREACH/CRIME attacks + # into the page tree snippets, as the javascript parsing the result + # expects a single top-level element. + (settings + .setdefault('RANDOM_COMMENT_EXCLUDED_VIEWS', set([])) + .add('cms.admin.pageadmin.get_tree')) + + return settings diff --git a/addons/aldryn-django-cms/settings.json b/addons/aldryn-django-cms/settings.json new file mode 100644 index 0000000..a411a61 --- /dev/null +++ b/addons/aldryn-django-cms/settings.json @@ -0,0 +1,7 @@ +{ + "boilerplate_name": "baker-street_gulp-scss", + "cms_content_cache_duration": 60, + "cms_menus_cache_duration": 3600, + "cms_templates": "[]", + "permissions_enabled": true +} \ No newline at end of file diff --git a/requirements.in b/requirements.in index 57e29f0..d4b57e7 100644 --- a/requirements.in +++ b/requirements.in @@ -2,6 +2,7 @@ https://control.divio.com/api/v1/apps/serve/aldryn-addons/1.0.2/24f5d1c8-66fe-43b2-a540-17d61045a72b/aldryn-addons-1.0.2.tar.gz#egg=aldryn-addons==1.0.2 https://control.divio.com/api/v1/apps/serve/aldryn-django/1.8.19.1/5dfa4420-e075-4377-a4b7-9feeaa3f5efb/aldryn-django-1.8.19.1.tar.gz#egg=aldryn-django==1.8.19.1 https://control.divio.com/api/v1/apps/serve/aldryn-sso/1.1.16/dbe0c45a-c981-4beb-8624-b0d2c4196aa0/aldryn-sso-1.1.16.tar.gz#egg=aldryn-sso==1.1.16 +https://control.divio.com/api/v1/apps/serve/aldryn-django-cms/3.5.1.3/2dd6f80a-825c-4aaf-b37f-519a6c46108e/aldryn-django-cms-3.5.1.3.tar.gz#egg=aldryn-django-cms==3.5.1.3 https://control.divio.com/api/v1/apps/serve/djangocms-file/2.0.2/f0e22a3c-8890-4013-93bc-02f0e937a570/djangocms-file-2.0.2.tar.gz#egg=djangocms-file==2.0.2 https://control.divio.com/api/v1/apps/serve/djangocms-googlemap/1.1.0/829bcfeb-0edc-4074-9483-88c27410d154/djangocms-googlemap-1.1.0.tar.gz#egg=djangocms-googlemap==1.1.0 https://control.divio.com/api/v1/apps/serve/djangocms-history/0.5.3/05803675-6e8d-4637-b14b-1bb8d18b24b3/djangocms-history-0.5.3.tar.gz#egg=djangocms-history==0.5.3 diff --git a/settings.py b/settings.py index 25e83d0..e17e7a3 100644 --- a/settings.py +++ b/settings.py @@ -5,6 +5,7 @@ INSTALLED_ADDONS = [ 'aldryn-addons', 'aldryn-django', 'aldryn-sso', + 'aldryn-django-cms', 'djangocms-file', 'djangocms-googlemap', 'djangocms-history',