示例#1
0
    def save(self, *args, **kwargs):
        """ Override the model's saving function to do some checks """
        # http://docs.djangoproject.com/en/dev/topics/db/models/
        #overriding-predefined-model-methods

        # Clean up the lures/distractors from empty items (blank lines)
        #if self.q_type in ('mcq', 'tf', 'multi'):
        #    if self.t_grading.has_key('lures'):
        #        self.t_grading['lures'] =  [lure for lure in
        #                                     self.t_grading['lures'] if
        #                                     lure.strip()]

        if isinstance(self.t_variables, dict):
            self.t_variables = json.dumps(self.t_variables, sort_keys=True)
        if isinstance(self.t_grading, dict):  # do not convert if its a string!
            self.t_grading = json.dumps(self.t_grading, sort_keys=True)
        self.max_grade = float(self.max_grade)
        self.difficulty = int(self.difficulty)
        self.difficulty = min(self.difficulty, 9)

        # http://docs.djangoproject.com/en/dev/topics/db/models/
        #overriding-predefined-model-methods
        if not self.slug:
            self.slug = generate_random_token(30)

        # Call the "real" save() method.
        super(QTemplate, self).save(*args, **kwargs)
示例#2
0
def peerreview_directory_path(instance, filename, randomize=True):
    """
    The file will be uploaded to MEDIA_ROOT/uploads/nnn/<filename>
    """
    if '.' not in filename:
        filename = filename + '.'
    extension = filename.split('.')[-1].lower()
    if randomize:
        filename = generate_random_token(token_length=16) + '.' + extension
    else:
        filename = ''.join(filename.split('.')[0:-1]) + '.' + extension
    return '{0}{1}{2}{1}{3}'.format('uploads', os.sep, instance.entry_point.id,
                                    filename)
示例#3
0
    def get(self):
        token = utils.generate_random_token(6)
        token_count = model.TokenCount.query().get()
        if not token_count:
            token_count = model.TokenCount()
            token_count.put()

        token = token + str(token_count.count)
        token_count.count += 1
        token_count.put()

        self.render_json({
            "token": token
            })
示例#4
0
def create_sign_in_email(user, qset=None):
    """
    Creates the token and generates the email body and subject for a user.
    """
    # Adjust the length of the authentication token here
    token_address = generate_random_token(token_length=10)
    Token.objects.get_or_create(token_address=token_address,
                                user=user,
                                has_been_used=False)
    token_address = token_prefix + token_address
    message = """\
    This message has been sent so you may access the Quest website.

    Sign in at: %s

    You may re-use this link within the testing duration, or request a new link
    from http://quest.mcmaster.ca\n\n""" % token_address

    if qset:
        subject = 'Quest website, %s' % qset.name
        message += """
    * Test duration = %s hours and %s minute(s).
    * Testing window closes at: %s.""" % \
          (qset.duration().hour,
           qset.duration().minute,
           qset.ans_time_final.strftime('%H:%M on %d %h %Y'))
    else:
        subject = 'Quest website access'

    #message += """

    #Please note: negative grading will be used for multiple-selection answers.
    #In other words, do not check an answer unless you are certain it is correct.
    #Negative grading is -0.5 points per incorrect selection.
    #"""

    message += """
    The http://quest.mcmaster.ca web server.
    """

    return subject, message, user.email
示例#5
0
def start_keyterm(request, course=None, learner=None, entry_point=None):
    """
    """
    if learner.role in ('Admin', ):
        return finalize_keyterm(request, course, learner, entry_point)

    prior = learner.keytermtask_set.filter(keyterm__entry_point=entry_point)
    if prior.count():
        keytermtask = prior[0]
        keyterm = keytermtask.keyterm
    else:
        # Create the new KeyTermTask for this learner
        try:
            keyterm = KeyTermSetting.objects.get(entry_point=entry_point)
        except KeyTermSetting.DoesNotExist:
            return HttpResponse(
                ('Please add KeyTermSetting to database first; '
                 "and don't forget to add the GradeItem too."))
        keytermtask = KeyTermTask(keyterm=keyterm,
                                  learner=learner,
                                  definition_text='',
                                  explainer_text='',
                                  reference_text='',
                                  is_in_draft=True,
                                  lookup_hash=generate_random_token())
        keytermtask.save()

    if request.POST.get('preview-keyterm', ''):
        return preview_keyterm(request, course, learner, entry_point)

    if request.POST.get('draft-keyterm', ''):
        return draft_keyterm(request, course, learner, entry_point)

    if request.POST.get('submit-keyterm', ''):
        return submit_keyterm(request, course, learner, entry_point)

    if request.POST.get('finalize-keyterm', '') or keytermtask.is_finalized:
        return finalize_keyterm(request, course, learner, entry_point)

    # If nothing else (usually the first time we start, we start with drafting)
    return draft_keyterm(request, course, learner, entry_point)
示例#6
0
def create_token_send_email_check_success(person, request):
    """ Used during signing in a new user, or an existing user. A token to
    is created, and an email is sent.
    If the email succeeds, then we return with success, else, we indicate
    failure to the calling function.
    """
    TOKEN_LENGTH = 9

    # Create a token for the new user
    hash_value = generate_random_token(TOKEN_LENGTH)

    # Send them a validation email
    send_validation_email(person, hash_value)
    info = get_course_ep_info(request)
    token = Token(person=person,
                  hash_value=hash_value,
                  next_uri='{}/course/{}/{}/'.format(
                      DJANGO_SETTINGS.BASE_URL, info['course'].label,
                      info['entry_point'].LTI_id))

    # All finished; return what we have (unsaved ``token`` instance)
    return token
示例#7
0
 def save(self, *args, **kwargs):
     if not (self.unique_code):
         self.unique_code = generate_random_token(token_length=16)
     super(EvaluationReport, self).save(*args, **kwargs)
示例#8
0
def create_preview(keytermtask):
    """
    Creates the keyterm page (PNG file), from the text, image, reference..
    Renders the image; uploads it as a submission.
    """
    entry_point = keytermtask.keyterm.entry_point

    # Settings for creating the image and thumbnail.
    targetWimg = int(1000)  # the pasted image is 1000 pixels wide
    targetWtxt = int(900)  # the text is 900 pixels wide
    targetW = targetWtxt + targetWimg
    targetHimg = int(1600)
    base_canvas_wh = (targetW, targetHimg)

    start_Lh = 0  # top left height coordinate (distance from top edge) of paste
    thumbWimg = thumbHimg = int(800)
    L_pad = R_pad = 20  # text padding
    bgcolor = "#EEE"
    color = "#000"
    REPLACEMENT_CHARACTER = u'\uFFFD'
    NEWLINE_REPLACEMENT_STRING = ' ' + REPLACEMENT_CHARACTER + ' '
    fontfullpath = settings.MEDIA_ROOT + 'keyterm/fonts/Lato-Regular.ttf'

    # These keyterms we will float the image left (odd numbers ID)
    if keytermtask.id % 2:
        start_Lw = 0  # top left width coordinate (distance from left
        # edge) of pasted image
        text_width = targetW
        L_pad += targetWimg

    # These keyterms will have float the image right
    else:
        start_Lw = targetWtxt  # top left width coordinate (distance from left
        # edge) of pasted image
        text_width = targetWtxt
        L_pad = L_pad  # stays the same ...

    # Is the storage space reachable?
    deepest_dir = settings.MEDIA_ROOT + 'uploads/{0}/thumbs/'.format(
        entry_point.id)

    try:
        os.makedirs(deepest_dir)
    except OSError:
        if not os.path.isdir(deepest_dir):
            logger.error(
                'Cannot create directory for upload: {0}'.format(deepest_dir))
            raise

    img = Image.new("RGB", base_canvas_wh, bgcolor)
    draw = ImageDraw.Draw(img)

    # https://www.snip2code.com/Snippet/1601691/Python-text-to-image-(png)-conversion-wi
    def text2png(text,
                 draw,
                 start_y=0,
                 fontsize=50,
                 leftpadding=3,
                 rightpadding=3,
                 width=2000):
        """
        width:        the size of the canvas
        leftpadding:  the starting point where we write text from
        rightpadding: the fartherest right edge where we can write text up to
        """
        #font = ImageFont.load_default()
        font = ImageFont.truetype(fontfullpath, fontsize)
        text = text.replace('\n\n', NEWLINE_REPLACEMENT_STRING)
        text = text.replace('\n', NEWLINE_REPLACEMENT_STRING)
        lines = []
        line = u""

        for word in text.split():
            if word == REPLACEMENT_CHARACTER:  # Give a blank line
                lines.append(
                    line[1:]
                )  # Slice the white space in the begining of the line
                line = u""
                lines.append(u"")  # blank line
            elif font.getsize(line + ' ' + word)[0] <= (width - rightpadding -
                                                        leftpadding):
                line += ' ' + word
            else:  #start a new line
                lines.append(line[1:])  #slice the white space
                line = u""

                #TODO: handle too long words at this point
                line += ' ' + word  # Assume no word alone can exceed line width

        if len(line) != 0:
            lines.append(line[1:])  # add last line

        line_height = font.getsize(text)[1]
        img_height = line_height * (len(lines) + 1)

        y = start_y
        for line in lines:
            if line == '':
                line = ' '
            draw.text((leftpadding, y), line, color, font=font)
            y += line_height

        return y, line_height

    last_y, line_height = text2png(keytermtask.keyterm.keyterm,
                                   draw,
                                   start_y=50,
                                   fontsize=75,
                                   leftpadding=L_pad,
                                   width=text_width)

    last_y, line_height = text2png(keytermtask.definition_text,
                                   draw,
                                   start_y=last_y + line_height * 1,
                                   fontsize=32,
                                   width=text_width,
                                   leftpadding=L_pad,
                                   rightpadding=R_pad)

    last_y, line_height = text2png('Example/Explanation:',
                                   draw,
                                   start_y=last_y + line_height * 2,
                                   fontsize=50,
                                   width=text_width,
                                   leftpadding=L_pad,
                                   rightpadding=R_pad)

    last_y, line_height = text2png(keytermtask.explainer_text,
                                   draw,
                                   start_y=last_y,
                                   fontsize=28,
                                   width=text_width,
                                   leftpadding=L_pad,
                                   rightpadding=R_pad)

    last_y, line_height = text2png('Reference:',
                                   draw,
                                   start_y=last_y + line_height * 2,
                                   fontsize=30,
                                   width=text_width,
                                   leftpadding=L_pad,
                                   rightpadding=R_pad)

    last_y, line_height = text2png(keytermtask.reference_text,
                                   draw,
                                   start_y=last_y,
                                   fontsize=20,
                                   width=text_width,
                                   leftpadding=L_pad,
                                   rightpadding=R_pad)
    text = 'Created by: ' + keytermtask.learner.display_name
    last_y, line_height = text2png(text,
                                   draw,
                                   start_y=img.size[1] - 2 * line_height,
                                   fontsize=20,
                                   width=text_width,
                                   leftpadding=L_pad,
                                   rightpadding=R_pad)

    source = Image.open(keytermtask.image_raw.file_upload)
    width, height = source.width, source.height

    if (height / width) < (targetHimg / targetWimg):
        # Current image has width as the limiting constraint. Set width to target.
        height = int(max(height / width * targetWimg, 1))
        width = targetWimg
        start_Lh = start_Lh + int((targetHimg - height) / 2)

    elif (height / width) > (targetHimg / targetWimg):
        # Current image has height as the limiting constraint. Set height to target.
        width = int(max(width / height * targetHimg, 1))
        height = targetHimg
        start_Lw = start_Lw + int((targetWimg - width) / 2)

    source = source.resize((width, height))
    img.paste(source, (start_Lw, start_Lh))

    base_name = generate_random_token(token_length=16) + '.' + OUTPUT_EXTENSION
    submitted_file_name_django = 'uploads/{0}/{1}'.format(
        entry_point.id, base_name)
    full_path = settings.MEDIA_ROOT + submitted_file_name_django
    img.save(full_path)

    keytermtask.image_modified = submitted_file_name_django
    keytermtask.save()

    # Repeat: make the uploaded image -> thumbnail
    submitted_file_name_django = 'uploads/{0}/thumbs/{1}'.format(
        entry_point.id, base_name)
    full_path = settings.MEDIA_ROOT + submitted_file_name_django
    width, height = source.size
    if (height / width) > (thumbHimg / thumbWimg):
        # Current image has width as the limiting constraint.
        # Set width to target; pick middle part (top to bottom) as thumbnail.
        height = int(max(height / width * thumbWimg, 1))
        width = thumbWimg
        source = source.resize((width, height))
        centerH = int(height / 2.0)
        cropTh = int(centerH - thumbHimg / 2.)
        cropBh = cropTh + thumbHimg
        source = source.crop((0, cropTh, thumbWimg, cropBh))

    if (height / width) <= (targetHimg / targetWimg):
        # Current image has height as the limiting constraint.
        # Set height to target; pick middle part (left to right) as thumbnail.
        width = int(max(width / height * thumbHimg, 1))
        height = thumbHimg
        source = source.resize((width, height))
        centerW = int(width / 2.0)
        cropLw = int(centerW - thumbWimg / 2.)
        cropRw = cropLw + thumbWimg
        source = source.crop((cropLw, 0, cropRw, thumbHimg))

    fill_color = ''  # your background
    if source.mode in ('RGBA', 'LA'):
        background = Image.new(source.mode[:-1], source.size, bgcolor)
        background.paste(source, source.split()[-1])
        source = background
    source.convert('RGB').save(full_path, quality=95)

    keytermtask.image_thumbnail = submitted_file_name_django
    keytermtask.save()
示例#9
0
async def randtoken(ctx):
    await ctx.channel.send(generate_random_token())
示例#10
0
 def save(self, *args, **kwargs):
     if not(self.rubric_code):
         self.rubric_code = generate_random_token(token_length=16)
     super(RubricActual, self).save(*args, **kwargs)
示例#11
0
def upload_submission(request, learner, trigger, no_thumbnail=True):
    """
    Handles the upload of the user's submission.
    """
    base_dir_for_file_uploads = settings.MEDIA_ROOT
    thumbnail_file_name_django = ''
    entry_point = trigger.entry_point

    files = request.FILES.getlist('file_upload', None)
    if files is None:
        return None

    # Is the storage space reachable?
    deepest_dir = base_dir_for_file_uploads + 'uploads/{0}/tmp/'.format(
        entry_point.id)

    try:
        os.makedirs(deepest_dir)
    except OSError:
        if not os.path.isdir(deepest_dir):
            logger.error(
                'Cannot create directory for upload: {0}'.format(deepest_dir))
            raise

    if len(files) == 1:
        filename = files[0].name
        extension = filename.split('.')[-1].lower()
        submitted_file_name_django = 'uploads/{0}/{1}'.format(
            entry_point.id,
            generate_random_token(token_length=16) + '.' + extension)
        full_path = base_dir_for_file_uploads + submitted_file_name_django
        with open(full_path, 'wb+') as dst:
            for chunk in files[0].chunks():
                dst.write(chunk)

        f_size = os.path.getsize(full_path)
        if f_size > trigger.max_file_upload_size_MB * 1024 * 1024:
            logger.warning(
                'File too large {0}'.format(submitted_file_name_django))
            return None, ('File too large ({0} MB); it must be less than '
                          '{1} MB.'.format(
                              round(float(f_size / 1024.0 / 1024.0), 1),
                              trigger.max_file_upload_size_MB))

    else:  #if trigger.allow_multiple_files: this is removed for now
        filename = ''
        extension = ''
        submitted_file_name_django = ''
        full_path = ''

    # Check that the file format is PDF, if that is required.
    strike1 = False
    if 'pdf' in trigger.accepted_file_types_comma_separated.lower() and \
       extension in ('pdf',):
        try:
            mime = magic.from_file(full_path, mime=True)
            if not (isinstance(mime, str)):
                mime = mime.decode('utf-8')
        except Exception as exp:
            logger.error('Could not determine MIME type: ' + str(exp))
            mime = ''
            strike1 = True

        if 'application/pdf' not in mime.lower():
            strike1 = True

        if strike1:
            logger.debug('Invalid PDF upload: {0} [{1}]'.format(
                mime, full_path))
            #return None, 'Invalid file uploaded. Uploaded file must be a PDF.'

        doc = PdfFileReader(full_path)
        if doc.isEncrypted:
            logger.debug('Encrypted PDF upload: {0}'.format(full_path))
            return None, ('An encrypted PDF cannot be uploaded. Please remove '
                          'the encryption and try again.')

    strike1 = False
    if (('jpeg' in trigger.accepted_file_types_comma_separated.lower()) or \
       ('jpg' in trigger.accepted_file_types_comma_separated.lower())) and \
       extension in ('jpg', 'jpeg'):

        try:
            mime = magic.from_file(full_path, mime=True)
            if not (isinstance(mime, str)):
                mime = mime.decode('utf-8')
        except Exception as exp:
            logger.error('Could not determine MIME type: ' + str(exp))
            mime = ''
            strike1 = True

        if 'image/jpeg' not in mime.lower():
            strike1 = True

        if strike1:
            logger.debug('Invalid JPG upload: {0} [{1}]'.format(
                mime, full_path))
            return None, ('Invalid file. Uploaded image should be a valid '
                          'and readable JPEG file.')

    strike1 = False
    if ('png' in trigger.accepted_file_types_comma_separated.lower()) and \
       extension in ('png',):

        try:
            mime = magic.from_file(full_path, mime=True)
            if not (isinstance(mime, str)):
                mime = mime.decode('utf-8')
        except Exception as exp:
            logger.error('Could not determine MIME type: ' + str(exp))
            mime = ''
            strike1 = True

        if 'image/png' not in mime.lower():
            strike1 = True

        if strike1:
            logger.debug('Invalid PNG upload: {0} [{1}]'.format(
                mime, full_path))
            return None, ('Invalid file. Uploaded image should be a valid '
                          'and readable PNG file.')

    strike2 = False
    if extension.lower() not in \
                            trigger.accepted_file_types_comma_separated.lower():
        logger.debug('Invalid file type upload: received ".{0}"; [{1}]'.format(\
                                                    extension, full_path))
        return None, ('Invalid file uploaded. Uploaded file must be: {}'.format(\
                                 trigger.accepted_file_types_comma_separated))

    if trigger == entry_point:
        # In some instances we don't use triggers, just entry_points
        prior = Submission.objects.filter(status='S',
                                          submitted_by=learner,
                                          entry_point=entry_point,
                                          is_valid=True)
    else:
        prior_indiv = Q(status='S',
                        submitted_by=learner,
                        entry_point=entry_point,
                        trigger=trigger,
                        is_valid=True)

        # We need this here, but also for the code later in the next
        # if (trigger==entry_point) part

        # Default returned by this function is ``None`` if the user is not
        # enrolled in a group, or if this course simply does not use groups.
        group_submitted = is_group_submission(learner, entry_point)
        if is_group_submission(learner, entry_point):
            group_submitted = group_submitted.group

            prior_group = Q(status='S',
                            group_submitted=group_submitted,
                            entry_point=entry_point,
                            trigger=trigger,
                            is_valid=True)
        else:
            prior_group = Q()

        prior = Submission.objects.filter(prior_indiv | prior_group)

    for item in prior:
        logger.debug(('Setting prior submission to False: {0} and name '
                      '"{1}"'.format(str(item), item.submitted_file_name)))
        item.is_valid = False
        item.save()

    if trigger == entry_point:
        # In some instances we don't use triggers, just entry_points
        sub = Submission(
            submitted_by=learner,
            group_submitted=None,
            status='S',
            entry_point=entry_point,
            is_valid=True,
            file_upload=submitted_file_name_django,
            thumbnail=thumbnail_file_name_django,
            submitted_file_name=filename,
            ip_address=get_IP_address(request),
        )
        sub.save()
    else:

        sub = Submission(
            submitted_by=learner,
            group_submitted=group_submitted,
            status='S',
            entry_point=entry_point,
            trigger=trigger,
            is_valid=True,
            file_upload=submitted_file_name_django,
            thumbnail=thumbnail_file_name_django,
            submitted_file_name=filename,
            ip_address=get_IP_address(request),
        )
        sub.save()

    if 'pdf' in trigger.accepted_file_types_comma_separated.lower() and \
                                                         extension in ('pdf',):
        clean_PDF(sub)

    return sub