コード例 #1
0
 def clean_File(self):
     file = clean_file_default(self)
     if get_ext(file.name) not in self.filetype.get_allowed_extensions():
         raise ValidationError(
             'This file extension is not allowed. Allowed extensions: ' +
             print_list(self.filetype.get_allowed_extensions()))
     return file
コード例 #2
0
 def clean(self):
     self.Caption = clean_text(self.Caption)
     if self.File:
         if get_ext(self.File.name) not in settings.ALLOWED_PUBLIC_FILES:
             raise ValidationError(
                 'This file type is not allowed. Allowed types: ' +
                 print_list(settings.ALLOWED_PUBLIC_FILES))
コード例 #3
0
 def clean(self):
     if self.File:
         if get_ext(self.File.name
                    ) not in settings.ALLOWED_PROJECT_ATTACHMENTS:
             raise ValidationError(
                 'This file type is not allowed. Allowed types: ' +
                 print_list(settings.ALLOWED_PROJECT_ATTACHMENTS))
コード例 #4
0
def clean_publicfile_default(self):
    file = clean_file_default(self)
    if get_ext(file.name) not in settings.ALLOWED_PUBLIC_FILES:
        raise ValidationError(
            'This file type is not allowed. Allowed types: ' +
            print_list(settings.ALLOWED_PUBLIC_FILES))
    return file
コード例 #5
0
 def clean(self):
     self.Caption = clean_text(self.Caption)
     if self.File:
         if get_ext(
                 self.File.name) not in self.Type.get_allowed_extensions():
             raise ValidationError(
                 'This file type is not allowed. Allowed types: ' +
                 print_list(self.Type.get_allowed_extensions()))
コード例 #6
0
def clean_attachment_default(self):
    """
    Check whether an attachment is valid

    :param self:
    :return:
    """
    file = clean_file_default(self)
    # this check is done both here and in the model
    if get_ext(file.name) not in settings.ALLOWED_PROJECT_ATTACHMENTS:
        raise ValidationError(
            'This file type is not allowed. Allowed types: ' +
            print_list(settings.ALLOWED_PROJECT_ATTACHMENTS))
    return file
コード例 #7
0
def download_all_of_student(request, pk=None):
    """
    Download all files for a student. Used at user info view for download all information of student.

    :param request:
    :param pk: id of the student
    :return:
    """
    if pk and get_grouptype('3') in request.user.groups.all(
    ):  # support can download for any user.
        user = get_object_or_404(User, pk=pk)
    elif not pk:  # student can download own files, ignore PK
        user = request.user
    else:
        raise PermissionDenied('Not allowed.')

    if user.groups.exists() or not user.distributions.exists():
        raise PermissionDenied('This is not a student user with files.')
    in_memory = BytesIO()
    with zipfile.ZipFile(in_memory, 'w') as archive:
        for dist in user.distributions.all():
            for file in dist.files.all():
                try:
                    name, ext = path.splitext(file.OriginalName)
                    name = path.basename(truncatechars(name, 25))
                    ext = get_ext(file.File.name)
                    with open(file.File.path, 'rb') as fstream:
                        archive.writestr(
                            '{}/{}/{}.{}'.format(str(dist.TimeSlot), file.Type,
                                                 name, ext), fstream.read())
                except (
                        IOError, ValueError
                ):  # happens if a file is referenced from database but does not exist on disk.
                    return render(
                        request, 'base.html', {
                            'Message':
                            'These files cannot be downloaded, please contact support staff. (Error on file: "{}")'
                            .format(file)
                        })
    in_memory.seek(0)

    response = HttpResponse(content_type="application/zip")
    response['Content-Disposition'] = 'attachment; filename="{}.zip"'.format(
        str(user.username))

    response.write(in_memory.read())

    return response
コード例 #8
0
def clean_studentfile_default(self):
    """
    Clean function for studentfile form. Checks if the extension is in the allowed extensions for this type file.

    :param self:
    :return:
    """
    try:
        ftype = get_object_or_404(FileType, pk=self.data['Type'])
    except:
        raise ValidationError(
            'Please select a file type from the drop-down list.')
    file = clean_file_default(self)
    if get_ext(file.name) not in ftype.get_allowed_extensions():
        raise ValidationError(
            'This file extension is not allowed. Allowed extensions: ' +
            print_list(ftype.get_allowed_extensions()))
    return file
コード例 #9
0
    def clean_File(self):
        """
        A check for an uploaded file. Checks filesize.

        :param self:
        :return:
        """
        file = self.cleaned_data.get("File")
        if file:
            s = file.size
            if s > settings.MAX_UPLOAD_SIZE:
                raise forms.ValidationError(
                    "The file is too large, it has to be at most " +
                    str(round(settings.MAX_UPLOAD_SIZE / 1024 / 1024)) +
                    "MB and is " + str(round(s / 1024 / 1024)) + "MB.")

            if get_ext(self.cleaned_data.get('File').name) != 'xlsx':
                raise forms.ValidationError(
                    f'File extension is not allowed, allowed extensions .xlsx')
        return file
コード例 #10
0
def clean_image_default(self):
    """
    Check whether an uploaded image is valid and has right dimensions

    :param self:
    :return:
    """
    picture = clean_file_default(self)

    # this check is done both here and in the model, needed to prevent wrong files entering get_image_dimensions()
    if get_ext(picture.name) not in settings.ALLOWED_PROJECT_IMAGES:
        raise ValidationError(
            'This file type is not allowed. Allowed types: ' +
            print_list(settings.ALLOWED_PROJECT_IMAGES))

    w, h = get_image_dimensions(picture)
    if w < minw or h < minh:
        raise ValidationError(
            "The image is too small, it has to be at least " + str(minw) +
            "px by " + str(minh) + "px and is only " + str(w) + "px by " +
            str(h) + "px.")

    return picture
コード例 #11
0
def project_files(request, fileid, project_id=None, ty=None):
    """
    project files, attachements or images, viewable on project details, model in projects-app
    Because projects images and attachements are seperate models, but are stored in the same folder, the ID is not
    unique, therefore only the UUID is possible to get the file.
    Mode 1: (old) projectid gives the folder to search in, fileid is the filename (an UUID)
    Mode 2: (new) ty is either "a" or "i" to refer to image or attachement and fileid is the ID (pk) of-
     the corresponding model
    When the file is an image, it is send inline, otherwise it is send as attachement.

    :param request:
    :param fileid: id of the project file.
    :param project_id: id of the project, corresponds to directory name appendix.
    :param ty: type, image or attachment
    :return: file download
    """
    if not request.user.is_authenticated:
        # allow anonymous users when viewing from a sharelink
        # make sure referrerpolicy is set on links, otherwise HTTP_REFERER might not be available.
        # https: // bugs.chromium.org / p / chromium / issues / detail?id = 455987
        if "HTTP_REFERER" in request.META:
            ref = request.META["HTTP_REFERER"].split('/')
            if 'share' in ref:  # url  /api/share/<sharetoken>/
                # check if sharetoken is valid. Same as in api.views
                try:
                    pk = signing.loads(ref[-2], max_age=settings.MAXAGESHARELINK)
                except signing.SignatureExpired:
                    raise PermissionDenied('Not allowed!')
                except signing.BadSignature:
                    raise PermissionDenied('Not allowed!')
                if not Proposal.objects.filter(pk=pk).exists():
                    # a check whether this image/attachment belongs to this project would be better
                    # but is more difficult.
                    raise PermissionDenied('Not allowed!')
                pass  # anonymous user viewing a valid share link
            else:
                raise PermissionDenied('Not allowed!')  # random referred
        else:  # direct access to file
            raise PermissionDenied('Not allowed!')

    # first try filename as image, then as attachment
    if project_id:  # via a project id and a filename (UUID) as fileid, the old way
        ext = get_ext(fileid)
        if ext in settings.ALLOWED_PROPOSAL_IMAGES:
            obj = get_object_or_404(ProposalImage, File='proposal_{}/{}'.format(project_id, fileid))
            return sendfile(request, obj.File.path, attachment=False)  # serve inline
        elif ext in settings.ALLOWED_PROPOSAL_ATTACHMENTS:
            obj = get_object_or_404(ProposalAttachment, File='proposal_{}/{}'.format(project_id, fileid))
            return sendfile(request, obj.File.path, attachment=True, attachment_filename=obj.OriginalName)
        else:
            raise PermissionDenied("File extension not allowed.")
    elif ty:  # by specifying image or attachement and a ID (pk) as fileid, the new way
        if ty == "a":  # attachment, like pdf
            obj = get_object_or_404(ProposalAttachment, id=fileid)
            return sendfile(request, obj.File.path, attachment=True, attachment_filename=obj.OriginalName)
        elif ty == "i":  # image
            obj = get_object_or_404(ProposalImage, id=fileid)
            return sendfile(request, obj.File.path)
        else:
            raise PermissionDenied("Invalid request.")
    else:
        raise PermissionDenied("Invalid request.")
コード例 #12
0
def download_files(request, timeslot):
    """
    all student files of PRV of timeslot

    :param request:
    :param timeslot: timeslot id.
    :return:
    """
    timeslot = get_object_or_404(TimeSlot, pk=timeslot)
    if timeslot == get_timeslot():  # current year
        if 4 > get_timephase_number(
        ) >= 0:  # only in phase 4, 5, 6 and 7 (although 4 is not useful)
            raise PermissionDenied(
                "This page is not available in the current time phase.")
    elif timeslot.End > datetime.now().date():  # future ts.
        raise PermissionDenied('Future timeslot.')

    in_memory = BytesIO()
    des = get_distributions(request.user, timeslot=timeslot)
    if not des:
        return render(request,
                      'base.html',
                      context={
                          'Message': 'You do not have students.',
                          'return': 'students:liststudents',
                          'returnget': timeslot.pk
                      })
    empty = True
    with zipfile.ZipFile(in_memory, 'w') as archive:
        for d in des:
            files = d.files.all()
            for file in files:
                empty = False
                try:
                    with open(file.File.path, 'rb') as fstream:
                        name, ext = path.splitext(file.OriginalName)
                        name = path.basename(truncatechars(name, 25))
                        ext = get_ext(file.File.name)
                        archive.writestr(
                            '{}-({})/{}/{}-{}.{}'.format(
                                d.Student.usermeta.Fullname,
                                d.Student.username, file.Type,
                                timezone.localtime(
                                    file.TimeStamp).strftime("%y%m%d%H%M%S"),
                                name, ext), fstream.read())
                except (
                        IOError, ValueError
                ):  # happens if a file is referenced from database but does not exist on disk.
                    return render(
                        request, 'base.html', {
                            'Message':
                            'These files cannot be downloaded, please contact support staff. (Error on file: "{}")'
                            .format(file)
                        })
    if empty:
        return render(
            request, 'base.html', {
                'Message': 'Your students did not upload any files yet.',
                'return': 'students:liststudents',
                'returnget': get_timeslot().pk
            })
    in_memory.seek(0)
    response = HttpResponse(content_type="application/zip")
    response[
        'Content-Disposition'] = f'attachment; filename="studentfiles {timeslot}.zip"'
    response.write(in_memory.read())
    return response