Example #1
0
class StorageWrapper:
    def __init__(self):
        self.storage = DefaultStorage()

    def save(self, filename: str, file_like):
        return self.storage.save(filename, file_like)

    def list(self, ext: str = None):
        _, files = self.storage.listdir("/")
        if ext:
            files = [f for f in files if f.endswith(ext)]
        return files

    def exists(self, filename: str):
        return self.storage.exists(filename)

    def find(self, filename: str) -> Optional[str]:
        for file_ in self.list():
            if file_ == filename:
                return file_
        return None

    def write_to(self, filename: str, callback: Any):
        f = self.storage.open(filename)
        callback(f.read())
        f.close()

    def remove(self, filename: str):
        self.storage.delete(filename)
Example #2
0
 def cleanup_files(self):
     """Remove stale screenshots"""
     storage = DefaultStorage()
     try:
         files = storage.listdir('screenshots')[1]
     except OSError:
         return
     for name in files:
         fullname = os.path.join('screenshots', name)
         if not Screenshot.objects.filter(image=fullname).exists():
             storage.delete(fullname)
Example #3
0
def cleanup_screenshot_files():
    """Remove stale screenshots"""
    storage = DefaultStorage()
    try:
        files = storage.listdir('screenshots')[1]
    except OSError:
        return
    for name in files:
        fullname = os.path.join('screenshots', name)
        if not Screenshot.objects.filter(image=fullname).exists():
            storage.delete(fullname)
Example #4
0
    def diagnostics(request):
        from django.conf import settings
        from post_office import mail

        ping_socket_url = (
            request.build_absolute_uri(f'{reverse("tracker:index_all")}ws/ping/')
            .replace('https:', 'wss:')
            .replace('http:', 'ws:')
        )

        celery_socket_url = (
            request.build_absolute_uri(f'{reverse("tracker:index_all")}ws/celery/')
            .replace('https:', 'wss:')
            .replace('http:', 'ws:')
        )

        if request.method == 'POST':
            test_email_form = TestEmailForm(data=request.POST)
            if test_email_form.is_valid():
                mail.send(
                    [test_email_form.cleaned_data['email']],
                    f'webmaster@{request.get_host().split(":")[0]}',
                    subject='Test Email',
                    message='If you got this, email is set up correctly.',
                )
                messages.info(
                    request, 'Test email queued. Check Post Office models for status.'
                )
        else:
            test_email_form = TestEmailForm()

        try:
            storage = DefaultStorage()
            output = storage.save(f'testfile_{int(time.time())}', BytesIO(b'test file'))
            storage.open(output).read()
            assert storage.exists(output)
            storage.delete(output)
            storage_works = True
        except Exception as e:
            storage_works = e

        return render(
            request,
            'admin/tracker/diagnostics.html',
            {
                'is_secure': request.is_secure(),
                'test_email_form': test_email_form,
                'ping_socket_url': ping_socket_url,
                'celery_socket_url': celery_socket_url,
                'storage_works': storage_works,
                'HAS_CELERY': getattr(settings, 'HAS_CELERY', False),
            },
        )
Example #5
0
    def cleanup(self, user):
        """Clean up the uploaded file.

        This will delete the uploaded file from the storage.

        Args:
            user (django.contrib.auth.models.User):
                The user.
        """
        settings_manager = self._settings_manager_class(user)
        configuration = settings_manager.configuration_for(self.avatar_service_id)

        storage = DefaultStorage()
        storage.delete(configuration["file_path"])
Example #6
0
    def cleanup(self, user):
        """Clean up the uploaded file.

        This will delete the uploaded file from the storage.

        Args:
            user (django.contrib.auth.models.User):
                The user.
        """
        settings_manager = self._settings_manager_class(user)
        configuration = settings_manager.configuration_for(
            self.avatar_service_id)

        storage = DefaultStorage()
        storage.delete(configuration['file_path'])
Example #7
0
 def handle(self, *args, **options) -> None:
     no_delete = options['no_delete']
     contents = self.make_file_contents()
     storage = DefaultStorage()
     self.stdout.write(
         f'Saving test file via {settings.DEFAULT_FILE_STORAGE}...\n')
     filename = storage.save('storetestfile_test_file.txt',
                             BytesIO(contents))
     self.stdout.write(f'Test file saved as "{filename}".\n')
     try:
         self.stdout.write('Validating test file...\n')
         assert storage.exists(filename)
         self.stdout.write('Test file exists.\n')
         with storage.open(filename) as f:
             assert f.read() == contents
             self.stdout.write('Test file contents are valid.\n')
     finally:
         if no_delete:
             self.stdout.write(f'Please delete "{filename}" manually.')
         else:
             self.stdout.write('Deleting test file...\n')
             storage.delete(filename)
     self.stdout.write('Done!\n')
Example #8
0
    def save(self, **kwargs):
        super().save(**kwargs)
        storage = DefaultStorage()

        if self._orig_image and not self.photo:
            storage.delete(self._orig_image)
            self._orig_image = None

        elif self.photo and self._orig_image != self.photo.name:
            original_image_name = self.photo.name
            logger.debug("Converting image %s", original_image_name)

            with self.photo.open() as image_handle:
                image = Image.open(image_handle)
                image.load()

            # Image.thumbnail does not upscale an image that is smaller
            image.thumbnail(settings.PHOTO_UPLOAD_SIZE, Image.ANTIALIAS)

            # Create new filename to store compressed image
            image_name, _ext = os.path.splitext(original_image_name)
            image_name = storage.get_available_name(f"{image_name}.jpg")
            with storage.open(image_name, "wb") as new_image_file:
                image.convert("RGB").save(new_image_file, "JPEG")
            self.photo.name = image_name
            super().save(**kwargs)

            # delete original upload.
            storage.delete(original_image_name)

            if self._orig_image:
                logger.info("deleting: %s", self._orig_image)
                storage.delete(self._orig_image)
            self._orig_image = self.photo.name
        else:
            logging.info("We already had this image, skipping thumbnailing")
def store_uploaded_file(
    request,
    file_key,
    allowed_file_types,
    base_storage_filename,
    max_file_size,
    validator=None,
):
    """
    Stores an uploaded file to django file storage.

    Args:
        request (HttpRequest): A request object from which a file will be retrieved.
        file_key (str): The key for retrieving the file from `request.FILES`. If no entry exists with this
            key, a `ValueError` will be thrown.
        allowed_file_types (list): a list of allowable file type extensions. These should start with a period
            and be specified in lower-case. For example, ['.txt', '.csv']. If the uploaded file does not end
            with one of these extensions, a `PermissionDenied` exception will be thrown. Note that the uploaded file
            extension does not need to be lower-case.
        base_storage_filename (str): the filename to be used for the stored file, not including the extension.
            The same extension as the uploaded file will be appended to this value.
        max_file_size (int): the maximum file size in bytes that the uploaded file can be. If the uploaded file
            is larger than this size, a `PermissionDenied` exception will be thrown.
        validator (function): an optional validation method that, if defined, will be passed the stored file (which
            is copied from the uploaded file). This method can do validation on the contents of the file and throw
            a `FileValidationException` if the file is not properly formatted. If any exception is thrown, the stored
            file will be deleted before the exception is re-raised. Note that the implementor of the validator function
            should take care to close the stored file if they open it for reading.

    Returns:
        Storage: the file storage object where the file can be retrieved from
        str: stored_file_name: the name of the stored file (including extension)

    """

    if file_key not in request.FILES:
        raise ValueError("No file uploaded with key '" + file_key + "'.")

    uploaded_file = request.FILES[file_key]
    try:
        file_extension = os.path.splitext(uploaded_file.name)[1].lower()
        if file_extension not in allowed_file_types:
            file_types = "', '".join(allowed_file_types)
            msg = ungettext(
                "The file must end with the extension '{file_types}'.",
                "The file must end with one of the following extensions: '{file_types}'.",
                len(allowed_file_types)).format(file_types=file_types)
            raise PermissionDenied(msg)

        if uploaded_file.size > max_file_size:
            msg = _("Maximum upload file size is {file_size} bytes.").format(
                file_size=max_file_size)
            raise PermissionDenied(msg)

        stored_file_name = base_storage_filename + file_extension

        file_storage = DefaultStorage()
        # If a file already exists with the supplied name, file_storage will make the filename unique.
        stored_file_name = file_storage.save(stored_file_name, uploaded_file)

        if validator:
            try:
                validator(file_storage, stored_file_name)
            except:
                file_storage.delete(stored_file_name)
                raise

    finally:
        uploaded_file.close()

    return file_storage, stored_file_name
Example #10
0
def store_uploaded_file(
        request, file_key, allowed_file_types, base_storage_filename, max_file_size, validator=None,
):
    """
    Stores an uploaded file to django file storage.

    Args:
        request (HttpRequest): A request object from which a file will be retrieved.
        file_key (str): The key for retrieving the file from `request.FILES`. If no entry exists with this
            key, a `ValueError` will be thrown.
        allowed_file_types (list): a list of allowable file type extensions. These should start with a period
            and be specified in lower-case. For example, ['.txt', '.csv']. If the uploaded file does not end
            with one of these extensions, a `PermissionDenied` exception will be thrown. Note that the uploaded file
            extension does not need to be lower-case.
        base_storage_filename (str): the filename to be used for the stored file, not including the extension.
            The same extension as the uploaded file will be appended to this value.
        max_file_size (int): the maximum file size in bytes that the uploaded file can be. If the uploaded file
            is larger than this size, a `PermissionDenied` exception will be thrown.
        validator (function): an optional validation method that, if defined, will be passed the stored file (which
            is copied from the uploaded file). This method can do validation on the contents of the file and throw
            a `FileValidationException` if the file is not properly formatted. If any exception is thrown, the stored
            file will be deleted before the exception is re-raised. Note that the implementor of the validator function
            should take care to close the stored file if they open it for reading.

    Returns:
        Storage: the file storage object where the file can be retrieved from
        str: stored_file_name: the name of the stored file (including extension)

    """

    if file_key not in request.FILES:
        raise ValueError("No file uploaded with key '" + file_key + "'.")

    uploaded_file = request.FILES[file_key]
    try:
        file_extension = os.path.splitext(uploaded_file.name)[1].lower()
        if file_extension not in allowed_file_types:
            file_types = "', '".join(allowed_file_types)
            msg = ungettext(
                "The file must end with the extension '{file_types}'.",
                "The file must end with one of the following extensions: '{file_types}'.",
                len(allowed_file_types)).format(file_types=file_types)
            raise PermissionDenied(msg)

        if uploaded_file.size > max_file_size:
            msg = _("Maximum upload file size is {file_size} bytes.").format(file_size=max_file_size)
            raise PermissionDenied(msg)

        stored_file_name = base_storage_filename + file_extension

        file_storage = DefaultStorage()
        # If a file already exists with the supplied name, file_storage will make the filename unique.
        stored_file_name = file_storage.save(stored_file_name, uploaded_file)

        if validator:
            try:
                validator(file_storage, stored_file_name)
            except:
                file_storage.delete(stored_file_name)
                raise

    finally:
        uploaded_file.close()

    return file_storage, stored_file_name
Example #11
0
def delete_storage_file(filename):
    storage = DefaultStorage()
    storage.delete(filename)
def task_email_user(user_pk,
                    template_key,
                    context,
                    attachments=None,
                    delete_attachments_after_send=True,
                    language_code=None,
                    email_from=None,
                    headers=None,
                    reply_to=None):
    '''
    Task to send email to user

    :param user_pk: User primary key (or None if no DB user is used)
    :param template_key: Template key
    :param context: Context variables as a dictionary
    :param attachments: Attachments as list of tuples (name, mimetype)
    :param delete_attachments_after_send: True = delete attachments from storage after sending email
    :param language_code: Language code for email template
    :return:
    '''

    if headers is None:
        headers = {}

    try:
        mailer_settings = settings.TEMPLATEMAILER
    except:
        mailer_settings = {}

    DEFAULT_LANGUAGE_CODE = mailer_settings.get("DEFAULT_LANGUAGE_CODE", "en")

    if attachments is None:
        attachments = []

    recipients = [
        user_pk,
    ]

    if settings.DEBUG and not mailer_settings.get("FORCE_DEBUG_OFF"):
        headers['X-DjangoTemplateMailer-Original-Recipients'] = ','.join(
            recipients)
        recipients = mailer_settings.get(
            "DEBUG_RECIPIENTS",
            [name_email[1] for name_email in settings.ADMINS])

    try:
        email_template = EmailTemplate.objects.get(key=template_key,
                                                   language_code=language_code)
    except:
        email_template = EmailTemplate.objects.get(
            key=template_key, language_code=DEFAULT_LANGUAGE_CODE)

    text_template = Template(email_template.plain_text)
    template_context = Context(context)

    text_body = text_template.render(template_context)

    if email_template.html:
        html_template = Template(email_template.html)
        html_body = html_template.render(template_context)
    else:
        html_body = None

    subject_template = Template(email_template.subject)
    subject = subject_template.render(template_context)

    email_from = email_from or mailer_settings.get(
        "FROM",
        list(map(lambda name_email1: name_email1[1], settings.ADMINS))[0])

    connection = mail.get_connection()
    email = mail.EmailMultiAlternatives(subject=subject,
                                        body=text_body,
                                        headers=headers,
                                        reply_to=reply_to,
                                        from_email=email_from,
                                        to=recipients,
                                        connection=connection)

    if html_body:
        email.attach_alternative(html_body, 'text/html')

    storage = DefaultStorage()

    if email_template.attachment:
        mimetype, att_encoding = mimetypes.guess_type(
            email_template.attachment.name)
        name = email_template.attachment.name
        f = storage.open(name)
        email.attach(basename(name), f.read(), mimetype)

    for (name, mimetype) in attachments:
        f = storage.open(name)
        email.attach(basename(name), f.read(), mimetype)
        if delete_attachments_after_send:
            storage.delete(name)

    email.send()