general: move asset management to its own app (#24450)
This commit is contained in:
parent
95893c29fe
commit
ce71720c40
|
@ -0,0 +1,34 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2017-2018 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 django.apps
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class AppConfig(django.apps.AppConfig):
|
||||
name = 'combo.apps.assets'
|
||||
verbose_name = _('Assets')
|
||||
|
||||
def get_before_urls(self):
|
||||
from . import urls
|
||||
return urls.urlpatterns
|
||||
|
||||
def get_extra_manager_actions(self):
|
||||
return [{'href': reverse('combo-manager-assets'),
|
||||
'text': _('Assets')}]
|
||||
|
||||
default_app_config = 'combo.apps.assets.AppConfig'
|
|
@ -0,0 +1,22 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2017-2018 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/>.
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class AssetUploadForm(forms.Form):
|
||||
upload = forms.FileField(label=_('File'))
|
|
@ -0,0 +1,33 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2017-2018 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/>.
|
||||
|
||||
from django.conf.urls import url, include
|
||||
|
||||
from combo.urls_utils import decorated_includes, manager_required
|
||||
|
||||
from . import views
|
||||
|
||||
assets_manager_urls = [
|
||||
url(r'^$', views.assets, name='combo-manager-assets'),
|
||||
url(r'^delete$', views.asset_delete, name='combo-manager-asset-delete'),
|
||||
url(r'^overwrite/$', views.asset_overwrite, name='combo-manager-asset-overwrite'),
|
||||
url(r'^upload/$', views.asset_upload, name='combo-manager-asset-upload'),
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^manage/assets/', decorated_includes(manager_required,
|
||||
include(assets_manager_urls))),
|
||||
]
|
|
@ -0,0 +1,144 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2017-2018 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 os
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.files.storage import default_storage
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.shortcuts import redirect
|
||||
from django.views.generic import TemplateView, ListView, FormView
|
||||
|
||||
import ckeditor
|
||||
|
||||
from .forms import AssetUploadForm
|
||||
|
||||
|
||||
class Asset(object):
|
||||
def __init__(self, filepath):
|
||||
self.filepath = filepath
|
||||
self.filename = os.path.basename(filepath)
|
||||
self.src = ckeditor.utils.get_media_url(filepath)
|
||||
|
||||
def css_classes(self):
|
||||
extension = os.path.splitext(self.filepath)[-1].strip('.')
|
||||
if extension:
|
||||
return 'asset-ext-%s' % extension
|
||||
return ''
|
||||
|
||||
def size(self):
|
||||
return os.stat(default_storage.path(self.filepath)).st_size
|
||||
|
||||
def thumb(self):
|
||||
if getattr(settings, 'CKEDITOR_IMAGE_BACKEND', None):
|
||||
thumb = ckeditor.utils.get_media_url(
|
||||
ckeditor.utils.get_thumb_filename(self.filepath))
|
||||
else:
|
||||
thumb = self.src
|
||||
return thumb
|
||||
|
||||
def is_image(self):
|
||||
return ckeditor.views.is_image(self.src)
|
||||
|
||||
|
||||
class Assets(ListView):
|
||||
template_name = 'combo/manager_assets.html'
|
||||
paginate_by = 10
|
||||
|
||||
def get_queryset(self):
|
||||
files = [Asset(x) for x in ckeditor.views.get_image_files(self.request.user)]
|
||||
q = self.request.GET.get('q')
|
||||
if q:
|
||||
files = [x for x in files if q.lower() in x.filename.lower()]
|
||||
files.sort(key=lambda x: getattr(x, 'filename'))
|
||||
return files
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(Assets, self).get_context_data(**kwargs)
|
||||
context['query'] = self.request.GET.get('q') or ''
|
||||
return context
|
||||
|
||||
assets = Assets.as_view()
|
||||
|
||||
|
||||
class AssetUpload(FormView):
|
||||
form_class = AssetUploadForm
|
||||
template_name = 'combo/manager_asset_upload.html'
|
||||
success_url = reverse_lazy('combo-manager-assets')
|
||||
|
||||
def form_valid(self, form):
|
||||
# use native ckeditor view so it's available from ckeditor file/image
|
||||
# dialogs.
|
||||
ckeditor_upload_view = ckeditor.views.ImageUploadView()
|
||||
self.request.GET = {'CKEditorFuncNum': '-'} # hack
|
||||
ckeditor_upload_view.post(self.request)
|
||||
return super(AssetUpload, self).form_valid(form)
|
||||
|
||||
asset_upload = AssetUpload.as_view()
|
||||
|
||||
|
||||
class AssetOverwrite(FormView):
|
||||
form_class = AssetUploadForm
|
||||
template_name = 'combo/manager_asset_overwrite.html'
|
||||
success_url = reverse_lazy('combo-manager-assets')
|
||||
|
||||
def form_valid(self, form):
|
||||
img_orig = self.request.GET['img']
|
||||
if '..' in img_orig:
|
||||
raise PermissionDenied() # better safe than sorry
|
||||
base_path = settings.CKEDITOR_UPLOAD_PATH
|
||||
if getattr(settings, 'CKEDITOR_RESTRICT_BY_USER', False):
|
||||
base_path = os.path.join(base_path, self.request.user.username)
|
||||
if not img_orig.startswith(base_path):
|
||||
raise PermissionDenied()
|
||||
|
||||
upload = self.request.FILES['upload']
|
||||
default_storage.delete(img_orig)
|
||||
if getattr(settings, 'CKEDITOR_IMAGE_BACKEND', None):
|
||||
thumb = ckeditor.utils.get_thumb_filename(img_orig)
|
||||
default_storage.delete(thumb)
|
||||
saved_path = default_storage.save(img_orig, upload)
|
||||
backend = ckeditor.image_processing.get_backend()
|
||||
upload.seek(0) # rewind file to be sure
|
||||
try:
|
||||
backend.image_verify(upload)
|
||||
except ckeditor.utils.NotAnImageException:
|
||||
pass
|
||||
else:
|
||||
if backend.should_create_thumbnail(saved_path):
|
||||
backend.create_thumbnail(saved_path)
|
||||
return super(AssetOverwrite, self).form_valid(form)
|
||||
|
||||
asset_overwrite = AssetOverwrite.as_view()
|
||||
|
||||
|
||||
class AssetDelete(TemplateView):
|
||||
template_name = 'combo/manager_asset_confirm_delete.html'
|
||||
|
||||
def post(self, request):
|
||||
img_orig = request.GET['img']
|
||||
if '..' in img_orig:
|
||||
raise PermissionDenied() # better safe than sorry
|
||||
base_path = settings.CKEDITOR_UPLOAD_PATH
|
||||
if getattr(settings, 'CKEDITOR_RESTRICT_BY_USER', False):
|
||||
base_path = os.path.join(base_path, request.user.username)
|
||||
if not img_orig.startswith(base_path):
|
||||
raise PermissionDenied()
|
||||
default_storage.delete(img_orig)
|
||||
return redirect(reverse('combo-manager-assets'))
|
||||
|
||||
asset_delete = AssetDelete.as_view()
|
|
@ -101,7 +101,3 @@ class PageEditExcludeFromNavigationForm(forms.ModelForm):
|
|||
|
||||
class SiteImportForm(forms.Form):
|
||||
site_json = forms.FileField(label=_('Site Export File'))
|
||||
|
||||
|
||||
class AssetUploadForm(forms.Form):
|
||||
upload = forms.FileField(label=_('File'))
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<a class="extra-actions-menu-opener"></a>
|
||||
<a rel="popup" href="{% url 'combo-manager-page-add' %}">{% trans 'New' %}</a>
|
||||
<ul class="extra-actions-menu">
|
||||
<li><a href="{% url 'combo-manager-assets' %}">{% trans 'Assets' %}</a></li>
|
||||
<li><a href="{% url 'combo-manager-site-export' %}">{% trans 'Export Site' %}</a></li>
|
||||
<li><a href="{% url 'combo-manager-site-import' %}">{% trans 'Import Site' %}</a></li>
|
||||
{% for extra_action in extra_actions %}
|
||||
|
|
|
@ -76,10 +76,6 @@ urlpatterns = [
|
|||
name='combo-manager-cell-order'),
|
||||
url(r'^pages/order$', views.page_order,
|
||||
name='combo-manager-page-order'),
|
||||
url(r'^assets/$', views.assets, name='combo-manager-assets'),
|
||||
url(r'^assets/delete$', views.asset_delete, name='combo-manager-asset-delete'),
|
||||
url(r'^assets/overwrite/$', views.asset_overwrite, name='combo-manager-asset-overwrite'),
|
||||
url(r'^assets/upload/$', views.asset_upload, name='combo-manager-asset-upload'),
|
||||
url(r'^ckeditor/upload/', staff_member_required(ckeditor_views.upload),
|
||||
name='ckeditor_upload'),
|
||||
url(r'^ckeditor/browse/', never_cache(staff_member_required(ckeditor_views.browse)),
|
||||
|
|
|
@ -17,11 +17,8 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import ckeditor
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.files.storage import default_storage
|
||||
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
|
@ -31,7 +28,7 @@ from django.utils.encoding import force_text
|
|||
from django.utils.formats import date_format
|
||||
from django.utils.timezone import localtime
|
||||
from django.views.decorators.csrf import requires_csrf_token
|
||||
from django.views.generic import (TemplateView, RedirectView, DetailView,
|
||||
from django.views.generic import (RedirectView, DetailView,
|
||||
CreateView, UpdateView, ListView, DeleteView, FormView)
|
||||
|
||||
from combo.data.models import Page, CellBase, ParentContentCell, PageSnapshot
|
||||
|
@ -42,7 +39,7 @@ from combo import plugins
|
|||
from .forms import (PageEditTitleForm, PageVisibilityForm, SiteImportForm,
|
||||
PageEditRedirectionForm, PageSelectTemplateForm, PageEditSlugForm,
|
||||
PageEditPictureForm, PageEditExcludeFromNavigationForm,
|
||||
AssetUploadForm, PageEditDescriptionForm)
|
||||
PageEditDescriptionForm)
|
||||
|
||||
|
||||
class HomepageView(ListView):
|
||||
|
@ -473,122 +470,6 @@ def page_get_additional_label(request, page_pk, cell_reference):
|
|||
return response
|
||||
|
||||
|
||||
class Asset(object):
|
||||
def __init__(self, filepath):
|
||||
self.filepath = filepath
|
||||
self.filename = os.path.basename(filepath)
|
||||
self.src = ckeditor.utils.get_media_url(filepath)
|
||||
|
||||
def css_classes(self):
|
||||
extension = os.path.splitext(self.filepath)[-1].strip('.')
|
||||
if extension:
|
||||
return 'asset-ext-%s' % extension
|
||||
return ''
|
||||
|
||||
def size(self):
|
||||
return os.stat(default_storage.path(self.filepath)).st_size
|
||||
|
||||
def thumb(self):
|
||||
if getattr(settings, 'CKEDITOR_IMAGE_BACKEND', None):
|
||||
thumb = ckeditor.utils.get_media_url(
|
||||
ckeditor.utils.get_thumb_filename(self.filepath))
|
||||
else:
|
||||
thumb = self.src
|
||||
return thumb
|
||||
|
||||
def is_image(self):
|
||||
return ckeditor.views.is_image(self.src)
|
||||
|
||||
|
||||
class Assets(ListView):
|
||||
template_name = 'combo/manager_assets.html'
|
||||
paginate_by = 10
|
||||
|
||||
def get_queryset(self):
|
||||
files = [Asset(x) for x in ckeditor.views.get_image_files(self.request.user)]
|
||||
q = self.request.GET.get('q')
|
||||
if q:
|
||||
files = [x for x in files if q.lower() in x.filename.lower()]
|
||||
files.sort(key=lambda x: getattr(x, 'filename'))
|
||||
return files
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(Assets, self).get_context_data(**kwargs)
|
||||
context['query'] = self.request.GET.get('q') or ''
|
||||
return context
|
||||
|
||||
assets = Assets.as_view()
|
||||
|
||||
|
||||
class AssetUpload(FormView):
|
||||
form_class = AssetUploadForm
|
||||
template_name = 'combo/manager_asset_upload.html'
|
||||
success_url = reverse_lazy('combo-manager-assets')
|
||||
|
||||
def form_valid(self, form):
|
||||
# use native ckeditor view so it's available from ckeditor file/image
|
||||
# dialogs.
|
||||
ckeditor_upload_view = ckeditor.views.ImageUploadView()
|
||||
self.request.GET = {'CKEditorFuncNum': '-'} # hack
|
||||
ckeditor_upload_view.post(self.request)
|
||||
return super(AssetUpload, self).form_valid(form)
|
||||
|
||||
asset_upload = AssetUpload.as_view()
|
||||
|
||||
|
||||
class AssetOverwrite(FormView):
|
||||
form_class = AssetUploadForm
|
||||
template_name = 'combo/manager_asset_overwrite.html'
|
||||
success_url = reverse_lazy('combo-manager-assets')
|
||||
|
||||
def form_valid(self, form):
|
||||
img_orig = self.request.GET['img']
|
||||
if '..' in img_orig:
|
||||
raise PermissionDenied() # better safe than sorry
|
||||
base_path = settings.CKEDITOR_UPLOAD_PATH
|
||||
if getattr(settings, 'CKEDITOR_RESTRICT_BY_USER', False):
|
||||
base_path = os.path.join(base_path, self.request.user.username)
|
||||
if not img_orig.startswith(base_path):
|
||||
raise PermissionDenied()
|
||||
|
||||
upload = self.request.FILES['upload']
|
||||
default_storage.delete(img_orig)
|
||||
if getattr(settings, 'CKEDITOR_IMAGE_BACKEND', None):
|
||||
thumb = ckeditor.utils.get_thumb_filename(img_orig)
|
||||
default_storage.delete(thumb)
|
||||
saved_path = default_storage.save(img_orig, upload)
|
||||
backend = ckeditor.image_processing.get_backend()
|
||||
upload.seek(0) # rewind file to be sure
|
||||
try:
|
||||
backend.image_verify(upload)
|
||||
except ckeditor.utils.NotAnImageException:
|
||||
pass
|
||||
else:
|
||||
if backend.should_create_thumbnail(saved_path):
|
||||
backend.create_thumbnail(saved_path)
|
||||
return super(AssetOverwrite, self).form_valid(form)
|
||||
|
||||
asset_overwrite = AssetOverwrite.as_view()
|
||||
|
||||
|
||||
class AssetDelete(TemplateView):
|
||||
template_name = 'combo/manager_asset_confirm_delete.html'
|
||||
|
||||
def post(self, request):
|
||||
img_orig = request.GET['img']
|
||||
if '..' in img_orig:
|
||||
raise PermissionDenied() # better safe than sorry
|
||||
base_path = settings.CKEDITOR_UPLOAD_PATH
|
||||
if getattr(settings, 'CKEDITOR_RESTRICT_BY_USER', False):
|
||||
base_path = os.path.join(base_path, request.user.username)
|
||||
if not img_orig.startswith(base_path):
|
||||
raise PermissionDenied()
|
||||
default_storage.delete(img_orig)
|
||||
return redirect(reverse('combo-manager-assets'))
|
||||
|
||||
asset_delete = AssetDelete.as_view()
|
||||
|
||||
|
||||
def menu_json(request):
|
||||
if settings.TEMPLATE_VARS.get('site_title'):
|
||||
label = _('Editing "%(site_title)s"') % settings.TEMPLATE_VARS
|
||||
|
|
|
@ -62,6 +62,7 @@ INSTALLED_APPS = (
|
|||
'combo.profile',
|
||||
'combo.manager',
|
||||
'combo.public',
|
||||
'combo.apps.assets',
|
||||
'combo.apps.dashboard',
|
||||
'combo.apps.wcs',
|
||||
'combo.apps.publik',
|
||||
|
|
Loading…
Reference in New Issue