import logging

from django.contrib.auth import get_user_model
from django.http import HttpResponseForbidden
from django.views.generic import RedirectView

from ipware.ip import get_ip

from .models import DataFile, DataFileKey, NewDataFileAccessLog

UserModel = get_user_model()

logger = logging.getLogger(__name__)


class DataFileDownloadView(RedirectView):
    """
    Log a download and redirect the requestor to its actual location.
    """

    permanent = False

    # pylint: disable=attribute-defined-outside-init
    def get(self, request, *args, **kwargs):
        self.data_file = DataFile.objects.get(pk=self.kwargs.get('pk'))

        if not self.data_file.has_access(user=request.user):
            return HttpResponseForbidden(
                '<h1>You do not have permission to access this file.</h1>')

        unavailable = (
            hasattr(self.data_file, 'parent_project_data_file') and
            self.data_file.parent_project_data_file.completed is False)
        if unavailable:
            return HttpResponseForbidden('<h1>This file is unavailable.</h1>')

        query_key = request.GET.get('key', None)
        if not self.data_file.is_public:
            if not query_key:
                return HttpResponseForbidden('<h1>No key provided.</h1>')
            key_qs = DataFileKey.objects.filter(datafile=self.data_file)
            key_qs = key_qs.filter(key=query_key)
            if not key_qs.exists():
                return HttpResponseForbidden('<h1>Incorrect key provided.</h1>')
            if key_qs.get().expired:
                return HttpResponseForbidden('<h1>Expired key.</h1>')
        return super().get(request, *args, **kwargs)

    def get_redirect_url(self, *args, **kwargs):
        user = (self.request.user
                if self.request.user.is_authenticated
                else None)

        access_log = NewDataFileAccessLog(
            user=user,
            ip_address=get_ip(self.request),
            data_file=self.data_file)
        access_log.save()

        return self.data_file.file_url_as_attachment

import logging

from django.contrib.auth import get_user_model
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.views.generic import View

from ipware.ip import get_ip

from .models import DataFile, DataFileKey, NewDataFileAccessLog

UserModel = get_user_model()

logger = logging.getLogger(__name__)


class DataFileDownloadView(View):
    """
    Log a download and redirect the requestor to its actual location.
    """

    def get_and_log(self, request):
        """
        Logs the file being accessed and then returns a redirect to the s3 url
        for that file
        """
        user = (request.user if request.user.is_authenticated else None)

        access_log = NewDataFileAccessLog(
            user=user,
            ip_address=get_ip(request),
            data_file=self.data_file)
        access_log.save()

        return HttpResponseRedirect(self.data_file.file_url_as_attachment)

    # pylint: disable=attribute-defined-outside-init
    def get(self, request, *args, **kwargs):
        self.data_file = DataFile.objects.get(pk=self.kwargs.get('pk'))

        unavailable = (
            hasattr(self.data_file, 'parent_project_data_file') and
            self.data_file.parent_project_data_file.completed is False)
        if unavailable:
            return HttpResponseForbidden('<h1>This file is unavailable.</h1>')

        if self.data_file.has_access(user=request.user):
            return self.get_and_log(request)

        query_key = request.GET.get('key', None)
        if query_key:
            key_qs = DataFileKey.objects.filter(datafile=self.data_file)
            key_qs = key_qs.filter(key=query_key)
            if key_qs.exists():
                if not key_qs.get().expired:
                    return self.get_and_log(request)
        return HttpResponseForbidden(
            '<h1>You are not authorized to view this file.</h1>')

Edit logic to allow file download if user is logged in, regardless of key state. (#938)