Commits

b7w committed 791e8e8

Revert new ProxyImageStorage, to commite 7fa75f2e0c046dd02d1cd6986b98bf1d7d163d4c

All function of new storage can provide file system.

  • Participants
  • Parent commits 5577dd4

Comments (0)

Files changed (20)

bviewer/api/tests/test_edit.py

         gallery_id = self.data.gallery_b7w.id
         album_id = self.data.album_b7w.id
 
-        self.new_gallery = dict(description='New gallery', user=user_id, url='test')
+        self.new_gallery = dict(title='New gallery', user=user_id, url='test')
         self.new_album = dict(title='New album', gallery=gallery_id)
-        self.new_image = dict(path='b7w_home/image1.jpg', album=album_id)
-        self.data.generate_image('b7w_home/image1.jpg')
+        self.new_image = dict(path='image1.jpg', album=album_id)
+        self.data.generate_image(self.data.gallery_b7w.home, 'image1.jpg')
         self.new_video = dict(uid='123456', title='New', album=album_id)
 
     def test_public_post(self):

bviewer/archive/controllers.py

 # -*- coding: utf-8 -*-
 import logging
 
-from bviewer.core.files.proxy import ProxyImageStorage
+from bviewer.core.files.storage import ImageStorage
 from bviewer.core.utils import ImageOptions, cache_method, as_job, get_redis_connection
 
 
         :type name: str
         """
         self.gallery = gallery
-        self.storage = ProxyImageStorage(gallery, archive_cache=True)
+        self.storage = ImageStorage(gallery, archive_cache=True)
         self.image_paths = [self.storage.get_path(i) for i in image_paths]
         self.name = name or self.uid
 

bviewer/core/controllers.py

 # -*- coding: utf-8 -*-
 import logging
 import re
-
 from django.conf import settings
 from django.core.cache import cache
 from django.db.models import Q
 from django.utils.encoding import smart_text
 
 from bviewer.core.exceptions import FileError
-from bviewer.core.files.proxy import ProxyImageStorage
 from bviewer.core.files.response import download_response
 from bviewer.core.files.storage import ImageStorage
 from bviewer.core.images import CacheImage
         """
         :type obj: bviewer.core.models.Album
         """
-        return AlbumController(obj, obj.user, obj=obj.top_album)
+        return AlbumController(obj.gallery, obj.gallery.user, obj=obj)
 
     @cache_method
     def get_object(self):
         sizes = [i for i in settings.VIEWER_IMAGE_SIZE.keys() if i != 'full']
         for size in sizes:
             for image in images:
-                storage = ProxyImageStorage(self.gallery)
+                storage = ImageStorage(self.gallery)
                 self._pre_cache_image(storage, image, size)
 
     def _pre_cache_image(self, storage, image, size):
     MODEL = Image
 
     def get_response(self, size):
-        # : :type: bviewer.core.models.Image
+        #: :type: bviewer.core.models.Image
         image = self.get_object()
-        storage = ProxyImageStorage(self.gallery)
+        storage = ImageStorage(self.gallery)
         options = ImageOptions.from_settings(size)
         image_path = storage.get_path(image.path, options)
         if not image_path.exists:
     MODEL = Video
 
     def get_response(self, size):
-        # : :type: bviewer.core.models.Video
+        #: :type: bviewer.core.models.Video
         video = self.get_object()
-        storage = ProxyImageStorage(self.gallery)
+        storage = ImageStorage(self.gallery)
         options = ImageOptions.from_settings(size, name=str(video.id))
         image_url = storage.get_url(video.thumbnail_url, options)
 

bviewer/core/files/base.py

-# -*- coding: utf-8 -*-
-import hashlib
-import uuid
-
-from django.utils.encoding import smart_bytes
-
-
-class BaseImageStorage(object):
-    def hash_for(self, content):
-        return hashlib.sha1(smart_bytes(content)).hexdigest()
-
-    def gen_temp_name(self):
-        return uuid.uuid1().hex

bviewer/core/files/path.py

         self.storage = storage
         self.id = None
         self.path = path
-        self.full_path = storage.gallery.home + '/' + path
         self.options = options
         self.name = os.path.basename(path)
         self.saved = False
         raise NotImplementedError()
 
 
-class MountPath(object):
-    def __init__(self, name):
-        self.name = name
-        self.full_path = name
-        self.is_image = False
-        self.is_dir = True
-
-    def __lt__(self, other):
-        return self.name < other.name
-
-
 class ImagePath(BasePath, ImagePathCacheMixin):
     """
     Provide basic operation on files, and cache.

bviewer/core/files/proxy.py

-# -*- coding: utf-8 -*-
-from bviewer.core.exceptions import FileError
-from bviewer.core.files.base import BaseImageStorage
-from bviewer.core.files.path import MountPath
-from bviewer.core.files.storage import ImageStorage
-from bviewer.core.files.utils import GalleryConfig
-
-
-class ProxyImageStorage(BaseImageStorage):
-    def __init__(self, gallery, root_path=None, cache_path=None, archive_cache=False, provider=ImageStorage):
-        """
-        :param root_path: place where image files stored, default settings.VIEWER_STORAGE_PATH
-        :param cache_path: place where cache stored, default settings.VIEWER_CACHE_PATH
-        :param archive_cache: set 'archives' sub cache folder instead of 'images'
-        :type gallery: bviewer.core.files.utils.GalleryConfig or bviewer.core.models.Gallery
-        """
-        self.gallery = gallery
-        self.mounts = sorted(set(gallery.home.split(';')))
-        self.configs = [GalleryConfig(gallery, i) for i in self.mounts]
-        self._storages = {}
-        for conf in self.configs:
-            storage = provider(conf, root_path=root_path, cache_path=cache_path, archive_cache=archive_cache)
-            self._storages[conf.home] = storage
-
-    def _get_storage(self, path):
-        for mount in self.mounts:
-            if path == mount:
-                return self._storages[mount], ''
-            _mount = mount + '/'
-            if path.startswith(_mount):
-                return self._storages[mount], path.replace(_mount, '')
-        raise FileError('No storage mount found')
-
-    def _get_master_storage(self):
-        return self._storages[self.mounts[0]]
-
-    def list(self, path=None, saved_images=None):
-        if not path:
-            return sorted(MountPath(i) for i in self.mounts)
-        storage, path = self._get_storage(path)
-        return storage.list(path, saved_images=saved_images)
-
-    def get_path(self, path, options=None):
-        storage, path = self._get_storage(path)
-        return storage.get_path(path, options=options)
-
-    def get_url(self, url, options=None):
-        storage = self._get_master_storage()
-        return storage.get_url(url, options=options)
-
-    def get_archive(self, options=None):
-        storage = self._get_master_storage()
-        return storage.get_archive(options=options)
-
-    def clear_cache(self, full=False):
-        for storage in self._storages.values():
-            storage.clear_cache(full=full)
-
-    def cache_size(self):
-        return sum(i.cache_size() for i in self._storages.values())
-
-    def __repr__(self):
-        return 'ProxyImageStorage({0})'.format(self.gallery)

bviewer/core/files/storage.py

 # -*- coding: utf-8 -*-
+from functools import wraps
 import hashlib
 import logging
 import os
 from django.conf import settings
 from django.utils.encoding import smart_bytes, smart_text
 
-from bviewer.core.files.base import BaseImageStorage
 from bviewer.core.files.path import ImagePath, ImageUrl, ImageArchivePath
 from bviewer.core.exceptions import FileError
 from bviewer.core.images import Exif
-from bviewer.core.utils import io_call
-
+from bviewer.core.utils import method_call_str
 
 logger = logging.getLogger(__name__)
 
 
-class ImageStorage(BaseImageStorage):
+def io_call(func):
+    """
+    Wrap method where can be raised `IOError` and re raise `FileError`.
+    Save method calls with all args to debug log.
+    """
+
+    @wraps(func)
+    def wrapper(self, *args, **kwargs):
+        try:
+            logger.debug(method_call_str(func.__name__, self, *args, **kwargs))
+            return func(self, *args, **kwargs)
+        except IOError as e:
+            print('1')
+            logger.exception(e)
+            raise FileError(e)
+
+    return wrapper
+
+
+class ImageStorage(object):
     """
     Wrapper on file system.
     Provide methods to get pre config ImagePath, ImageUrl, ImageArchivePath.
         :param root_path: place where image files stored, default settings.VIEWER_STORAGE_PATH
         :param cache_path: place where cache stored, default settings.VIEWER_CACHE_PATH
         :param archive_cache: set 'archives' sub cache folder instead of 'images'
-        :type gallery: bviewer.core.files.utils.GalleryConfig or bviewer.core.models.Gallery
+        :type gallery: bviewer.core.models.Gallery
         """
         self.gallery = gallery
         self.root = root_path or settings.VIEWER_STORAGE_PATH
             image_path = ImagePath(self, relative_path)
             if image_path.is_image or image_path.is_dir:
                 for obj in saved_images:
-                    if obj.path == image_path.full_path:
+                    if obj.path == image_path.path:
                         image_path.saved = True
                         image_path.id = obj.id
                         break
                 while sum(map(os.path.getsize, cache_paths)) > self._max_cache_size:
                     os.remove(cache_paths.pop())
 
+
     @io_call
     def cache_size(self):
         abs_cache = self._abs_cache_path

bviewer/core/files/utils.py

                 return data
             return data
 
-        return _split(self.path, [])
-
-
-class GalleryConfig(object):
-    def __init__(self, gallery, mount):
-        self.gallery = gallery
-        self.home = mount
-        self.url = gallery.url
-        self.cache_size = gallery.cache_size
-        self.cache_archive_size = gallery.cache_archive_size
-
-    def __str__(self):
-        return 'GalleryConfig({0}, {1})'.format(self.gallery, self.home)
+        return _split(self.path, [])

bviewer/core/management/commands/clearcache.py

 
 from django.core.management.base import BaseCommand
 
-from bviewer.core.files.proxy import ProxyImageStorage
+from bviewer.core.files.storage import ImageStorage
 from bviewer.core.models import Gallery
 
 
     def handle(self, *args, **options):
         full = 'full' in args
         for user in Gallery.objects.all():
-            ProxyImageStorage(user).clear_cache(full=full)
-            ProxyImageStorage(user, archive_cache=True).clear_cache(full=full)
+            ImageStorage(user).clear_cache(full=full)
+            ImageStorage(user, archive_cache=True).clear_cache(full=full)
         self.stdout.write('Clear cache for {c} users'.format(c=Gallery.objects.count()))

bviewer/core/models.py

 import json
 import logging
 import uuid
-from bviewer.core.files.proxy import ProxyImageStorage
 
 try:
     from urllib2 import urlopen, URLError
         """
         Check path exists
         """
-        storage = ProxyImageStorage(self.album.gallery)
-        if not storage.get_path(self.path).exists:
+        storage = ImageStorage(self.album.gallery)
+        if not storage.exists(self.path):
             raise ValidationError(smart_text('No {0} path exists').format(self.path))
 
     def __str__(self):
     :type instance: Image
     """
     if created:
-        storage = ProxyImageStorage(instance.album.gallery)
+        storage = ImageStorage(instance.album.gallery)
         set_time_from_exif(storage, instance, save=True)
 
 

bviewer/core/tests/base.py

 # -*- coding: utf-8 -*-
 import os
 import shutil
+from mock import Mock
 
-from mock import Mock
 from django.conf import settings
 from django.core import urlresolvers
 from django.test import TestCase

bviewer/core/tests/data.py

         user.save()
 
     def load_galleries(self):
-        self.gallery_b7w = Gallery(user=self.user_b7w, home='b7w_home')
+        self.gallery_b7w = Gallery(user=self.user_b7w)
         self.gallery_b7w.save()
-        self.gallery_keks = Gallery(user=self.user_keks, home='keks_home')
+        self.gallery_keks = Gallery(user=self.user_keks)
         self.gallery_keks.save()
         return self
 
         self.album5.save()
         return self
 
-    def generate_image(self, name, force=False):
+    def generate_image(self, home, name, force=False):
         """
         Create random image in settings.VIEWER_STORAGE_PATH if not exists.
         Or user `force=True` to override.
         """
-        path = os.path.join(settings.VIEWER_STORAGE_PATH, name)
+        path = os.path.join(settings.VIEWER_STORAGE_PATH, home, name)
         if not os.path.exists(os.path.dirname(path)):
             os.makedirs(os.path.dirname(path))
         if not os.path.exists(path) or force:
             image.save(path)
 
     def load_images(self):
-        self.image1 = Image.objects.create(album=self.album1, path='b7w_home/image1.jpg')
-        self.image2 = Image.objects.create(album=self.album1, path='b7w_home/image2.jpg')
-        self.generate_image(self.image1.path)
-        self.generate_image(self.image2.path)
+        self.image1 = Image.objects.create(album=self.album1, path='image1.jpg')
+        self.image2 = Image.objects.create(album=self.album1, path='image2.jpg')
+        self.generate_image(self.album1.gallery.home, self.image1.path)
+        self.generate_image(self.album1.gallery.home, self.image2.path)
 
-        self.image3 = Image.objects.create(album=self.album2, path='b7w_home/image3.jpg')
-        self.image4 = Image.objects.create(album=self.album2, path='b7w_home/image4.jpg')
-        self.generate_image(self.image3.path)
-        self.generate_image(self.image4.path)
+        self.image3 = Image.objects.create(album=self.album2, path='image3.jpg')
+        self.image4 = Image.objects.create(album=self.album2, path='image4.jpg')
+        self.generate_image(self.album2.gallery.home, self.image3.path)
+        self.generate_image(self.album2.gallery.home, self.image4.path)
 
-        self.image5 = Image.objects.create(album=self.album5, path='keks_home/image5.jpg')
-        self.generate_image(self.image5.path)
+        self.image5 = Image.objects.create(album=self.album5, path='image5.jpg')
+        self.generate_image(self.album5.gallery.home, self.image5.path)
         return self
 
     def load_videos(self):

bviewer/core/tests/test_controllers.py

         gallery = data.gallery_b7w
         top_album = gallery.top_album
 
-        controller = AlbumController(gallery, gallery.user, uid=top_album.id)
+        controller = AlbumController(gallery, gallery, uid=top_album.id)
         self.assertEqual(controller.uid, top_album.id)
         self.assertIsNone(controller.obj)
         self.assertEqual(controller.get_object(), top_album)
 
-        controller = AlbumController(gallery, gallery.user, obj=top_album)
+        controller = AlbumController(gallery, gallery, obj=top_album)
         self.assertEqual(controller.uid, top_album.id)
         self.assertEqual(controller.obj, top_album)
         self.assertEqual(controller.get_object(), top_album)

bviewer/core/tests/test_files.py

 # -*- coding: utf-8 -*-
 import os
+from mock import Mock, patch
 
-from mock import Mock, patch
 from django.test import TestCase
 from django.utils import six
 
 from bviewer.core.exceptions import FileError
 from bviewer.core.files.path import ImagePath
-from bviewer.core.files.proxy import ProxyImageStorage
 from bviewer.core.files.storage import ImageStorage
 from bviewer.core.files.utils import ImageFolder
 from bviewer.core.tests.base import BaseImageStorageTestCase
 
 class ImagePathTestCase(TestCase):
     def setUp(self):
-        self.storage = Mock(gallery=Mock(home='home'), hash_for=str)
+        self.storage = Mock(hash_for=str)
         self.f1 = ImagePath(self.storage, 'path/1.jpg')
         self.f2 = ImagePath(self.storage, 'path/2.jpg')
 
     def test_url(self):
         storage = Mock(
             hash_for=Mock(return_value='cache_name'),
-            gallery=Mock(home='home', url='gallery.url'),
+            gallery=Mock(url='gallery.url'),
             type='type'
         )
         self.assertEqual(storage.hash_for(), 'cache_name')
                 self.assertEqual(func(image_path, for_cache=True), for_cache)
 
         gallery = Mock(home='home', url='url', cache_size=0)
-        # storage try to create cache folder on init, mock it
-        with patch('os.makedirs'):
-            storage = ImageStorage(gallery, root_path='root', cache_path='cache')
+        storage = ImageStorage(gallery, root_path='root', cache_path='cache')
 
         assert_method_for_cache('os.path.getctime', storage.ctime, side_effect=str)
         assert_method_for_cache('os.path.exists', storage.exists, side_effect=str)
         open_module = 'builtins.open' if six.PY3 else '__builtin__.open'
-        assert_method_for_cache(open_module, storage.open, side_effect=lambda path, mode: str(path))
-
-
-class ProxyImageStorageTestCase(BaseImageStorageTestCase):
-    VALUE = Mock()
-    VALUE2 = Mock()
-
-    def setUp(self):
-        self.gallery = Mock(home='home;home2', url='gallery_url', cache_size=0)
-        self.backend = Mock(
-            list=Mock(return_value=self.VALUE),
-            get_path=Mock(return_value=self.VALUE),
-            get_url=Mock(return_value=self.VALUE),
-            get_archive=Mock(return_value=self.VALUE),
-            clear_cache=Mock(return_value=self.VALUE),
-            cache_size=Mock(return_value=10),
-        )
-        self.backend2 = Mock(
-            list=Mock(return_value=self.VALUE2),
-            get_path=Mock(return_value=self.VALUE2),
-            clear_cache=Mock(return_value=self.VALUE2),
-            cache_size=Mock(return_value=100),
-        )
-        self.storage = self._build_storage(self.backend, self.backend2)
-        self.options = Mock()
-
-    def _build_storage(self, backend, backend2):
-        def _provider(conf, *args, **kwargs):
-            if conf.home == 'home':
-                return backend
-            if conf.home == 'home2':
-                return backend2
-            raise AssertionError('Wrong home')
-
-        return ProxyImageStorage(self.gallery, provider=_provider)
-
-    def test_list(self):
-        out = self.storage.list(saved_images=self.options)
-        self.assertEqual([i.full_path for i in out if i.is_dir], ['home', 'home2'])
-
-        self.assertEqual(self.storage.list('home', saved_images=self.options), self.VALUE)
-        self.backend.list.assert_called_with('', saved_images=self.options)
-        self.assertEqual(self.storage.list('home/path', saved_images=self.options), self.VALUE)
-        self.backend.list.assert_called_with('path', saved_images=self.options)
-
-        self.assertEqual(self.storage.list('home2', saved_images=self.options), self.VALUE2)
-        self.backend2.list.assert_called_with('', saved_images=self.options)
-        self.assertEqual(self.storage.list('home2/path2', saved_images=self.options), self.VALUE2)
-        self.backend2.list.assert_called_with('path2', saved_images=self.options)
-
-    def test_get_path(self):
-        out = self.storage.get_path('home/file', options=self.options)
-        self.assertEqual(out, self.VALUE)
-        self.backend.get_path.assert_called_with('file', options=self.options)
-
-        out = self.storage.get_path('home2/file2', options=self.options)
-        self.assertEqual(out, self.VALUE2)
-        self.backend2.get_path.assert_called_with('file2', options=self.options)
-
-    def test_get_url(self):
-        out = self.storage.get_url('url', options=self.options)
-        self.assertEqual(out, self.VALUE)
-        self.backend.get_url.assert_called_with('url', options=self.options)
-
-    def test_get_archive(self):
-        out = self.storage.get_archive(options=self.options)
-        self.assertEqual(out, self.VALUE)
-        self.backend.get_archive.assert_called_with(options=self.options)
-
-    def test_clear_cache(self):
-        self.storage.clear_cache(full=True)
-        self.backend.clear_cache.assert_called_with(full=True)
-        self.backend2.clear_cache.assert_called_with(full=True)
-
-    def test_cache_size(self):
-        out = self.storage.cache_size()
-        self.assertEqual(out, 110)
-        self.backend.cache_size.assert_called_with()
-        self.backend2.cache_size.assert_called_with()
+        assert_method_for_cache(open_module, storage.open, side_effect=lambda path, mode: str(path))

bviewer/core/tests/test_images.py

 # -*- coding: utf-8 -*-
 from datetime import datetime
-
 from django.utils.timezone import utc
 
 from bviewer.core.images import CacheImage
         super(CacheImageTestCase, self).setUp()
         self.data = TestData()
         self.path = 'image1.jpg'
-        self.data.generate_image(self.gallery.home + '/' + self.path)
+        self.data.generate_image(self.gallery.home, self.path)
 
     def assertCacheImage(self, options, download=False):
         image_path = self.storage.get_path(self.path, options)
         super(ExifTest, self).setUp()
         self.data = TestData()
         self.path = 'image1.jpg'
-        self.data.generate_image(self.gallery.home + '/' + self.path)
+        self.data.generate_image(self.gallery.home, self.path)
 
     def test_ctime(self):
         exif = self.storage.exif(self.path)

bviewer/core/utils.py

 from django.utils.encoding import smart_text, smart_bytes
 from django.utils.functional import wraps
 
-from bviewer.core.exceptions import ResizeOptionsError, FileError
+from bviewer.core.exceptions import ResizeOptionsError
 
 
 logger = logging.getLogger(__name__)
     if image_path.is_image and image_path.exif.ctime:
         image.time = image_path.exif.ctime
         if save:
-            image.save()
-
-
-def io_call(func):
-    """
-    Wrap method where can be raised `IOError` and re raise `FileError`.
-    Save method calls with all args to debug log.
-    """
-
-    @wraps(func)
-    def wrapper(self, *args, **kwargs):
-        try:
-            logger.debug(method_call_str(func.__name__, self, *args, **kwargs))
-            return func(self, *args, **kwargs)
-        except IOError as e:
-            logger.exception(e)
-            raise FileError(e)
-
-    return wrapper
+            image.save()

bviewer/profile/actions.py

 # -*- coding: utf-8 -*-
 import logging
-
 from django.contrib import admin
 from django.db.models import F
 from django.shortcuts import redirect, render
 
-from bviewer.core.files.proxy import ProxyImageStorage
 from bviewer.core.utils import set_time_from_exif
+from bviewer.core.files.storage import ImageStorage
 from bviewer.profile.forms import BulkTimeUpdateForm
 
 
 
 def update_time_from_exif(model_admin, request, queryset):
     for image in queryset:
-        storage = ProxyImageStorage(image.album.user)
+        storage = ImageStorage(image.album.user)
         set_time_from_exif(storage, image, save=True)

bviewer/profile/admin.py

 from django.utils.encoding import smart_text
 
 from bviewer.core.controllers import AlbumController
-from bviewer.core.files.proxy import ProxyImageStorage
+from bviewer.core.files.storage import ImageStorage
 from bviewer.core.models import Album, Image, Gallery, Video
 from bviewer.profile.actions import bulk_time_update, update_time_from_exif
 from bviewer.profile.forms import AdminUserChangeForm, AdminGalleryForm, AdminAlbumForm
     form = AdminGalleryForm
 
     list_display = ('url', 'top_album', 'description', )
+    exclude = ('user',)
 
-    readonly_fields = ('home', 'cache_info', )
-    exclude = ('user',)
+    readonly_fields = ('cache_info', )
 
     ordering = ('url',)
 
     def cache_info(self, user):
-        storage = ProxyImageStorage(user)
+        storage = ImageStorage(user)
         images_size = storage.cache_size() / 2 ** 20
-        storage = ProxyImageStorage(user, archive_cache=True)
+        storage = ImageStorage(user, archive_cache=True)
         archive_size = storage.cache_size() / 2 ** 20
         return 'Images size: {0} MB, archives size: {1} MB'.format(images_size, archive_size)
 

bviewer/profile/templates/profile/images.html

                     </li>
                     {% for dir in folder.dirs %}
                         <li>
-                            <a href="{% url 'profile.album' album.id %}?p={{ dir.full_path }}" class="thumbnail">
+                            <a href="{% url 'profile.album' album.id %}?p={{ dir.path }}" class="thumbnail">
                                 <img src="{% static 'core/img/album.png' %}">
 
                                 <p class="caption">{{ dir.name }}</p>
                             <a class="thumbnail image">
                                 <input type='checkbox' class="caption-checkbox"
                                        data-id="{{ file.id }}"
-                                       data-value="{{ file.full_path }}"
+                                       data-value="{{ file.path }}"
                                        {% if file.saved %}checked{% endif %}>
-                                <img src="{% url 'profile.download' %}?p={{ file.full_path }}">
+                                <img src="{% url 'profile.download' %}?p={{ file.path }}">
 
                                 <p class="caption">{{ file.name }}</p>
                             </a>

bviewer/profile/views.py

 # -*- coding: utf-8 -*-
 import logging
-
 from django.contrib.auth.decorators import login_required, permission_required
 from django.http import Http404, HttpResponseRedirect
 from django.shortcuts import render
 
 from bviewer.core.controllers import get_gallery, AlbumController
 from bviewer.core.exceptions import FileError
-from bviewer.core.files.proxy import ProxyImageStorage
 from bviewer.core.files.response import download_response
+from bviewer.core.files.storage import ImageStorage
 from bviewer.core.files.utils import ImageFolder
 from bviewer.core.images import CacheImage
 from bviewer.core.utils import ImageOptions, as_job
         return message_view(request, message='No such album')
 
     images = controller.get_images()
-    storage = ProxyImageStorage(gallery)
+    storage = ImageStorage(gallery)
     path = request.GET.get('p', '')
     try:
         image_paths = storage.list(path, saved_images=images)
 def download_image(request):
     if request.GET.get('p', None):
         path = request.GET['p']
-        gallery = get_gallery(request)
-        storage = ProxyImageStorage(gallery)
+        user = get_gallery(request)
+        storage = ImageStorage(user)
         options = ImageOptions.from_settings('tiny')
         image_path = storage.get_path(path, options)
         try: