Пример #1
0
def comment_new(id):
    post = Post.get_by_id(id)

    if post is None or post.is_hidden:
        abort(404)

    form = CommentForm()

    if form.is_submitted():
        try:
            if not form.validate():
                raise Exception(_('ERROR_INVALID_SUBMISSION'))

            comment = Comment(user=current_user, post=post)
            form.populate_obj(comment)
            comment.save()

            flash(_('COMMENT_SAVE_SUCESS'))

            if comment.parent_comment:
                send_email('reply_comment', comment)
            else:
                send_email('comment', post, comment)

            return redirect(url_for('stamp.show',
                                    id=post.id,
                                    _anchor='comment-%s' % comment.id))

        except Exception as e:
            flash(e.message, 'error')

    return render_template('main/stamp/show.html',
                           post=post,
                           form=form)
Пример #2
0
def comment_new(id):
    post = Post.get_by_id(id)

    if post is None or post.is_hidden:
        abort(404)

    form = CommentForm()

    if form.is_submitted():
        try:
            if not form.validate():
                raise Exception(_('ERROR_INVALID_SUBMISSION'))

            comment = Comment(user=current_user, post=post)
            form.populate_obj(comment)
            comment.save()

            flash(_('COMMENT_SAVE_SUCESS'))

            if comment.parent_comment:
                send_email('reply_comment', comment)
            else:
                send_email('comment', post, comment)

            return redirect(
                url_for('stamp.show',
                        id=post.id,
                        _anchor='comment-%s' % comment.id))

        except Exception as e:
            flash(e.message, 'error')

    return render_template('main/stamp/show.html', post=post, form=form)
Пример #3
0
def password_reset_request():
    form = PasswordResetRequestForm()
    if form.validate_on_submit():
        def accept(t):
            return PasswordResetRequest.query.filter_by(token=t).first() is None
        token = random_base64(accept)
        reset_link = url_for('auth.password_reset', _external=True, token=token)
        try:
            send_email(
                subject="Reset your Asset Tracker Password",
                sender=form.email.data,
                recipients=[form.email.data],
                body="Asset Tracker password reset link: %s\r\n\r\n\
                     This link will expire in 24 hours" % reset_link,
                html="Asset Tracker password reset link:<br> <a href=\"%s\">\
                     %s</a> <br><br>This link will expire in 24 hours" %
                     (reset_link, reset_link)
            )
            entry = PasswordResetRequest(
                token,
                User.query.filter_by(email=form.email.data).first()
            )
            db.session.add(entry)
            db.session.commit()
            flash("A link to reset your password has been sent to %s" %
                  form.email.data, "success")

        except Exception, e:
            if current_app.config.get('DEBUG'):
                raise e
            else:
                flash("Failed to send invite due to a %s error"
                      % e.__class__.__name__, 'danger')
def request_new_topic():
    if session['acc_type'] != 'student':
        # only students are allowed to request topics
        # disallow ALL other users from requesting
        return error('You must be a student to request a topic!')
    try:
        fields = ['topic', 'message']
        topic, message = get_fields(request.form, fields)
    except ValueError as e:
        return e.args[0]
    db.connect()

    res = db.select_columns('topics', ['id', 'name', 'supervisor', 'visible'],
                            ['id'], [topic])
    topic_name = res[0][1]
    supervisor = res[0][2]

    if not len(res):
        db.close()
        return error('No such topic exists!')
    if not int(res[0][3]):
        db.close()
        return error('This topic is not available to request!')

    res = db.select_columns('request_statuses', ['id'], ['name'], ['pending'])

    user_id = session['id']
    now = datetime.now().timestamp()
    try:
        db.insert_single(
            'topic_requests', [user_id, topic, res[0][0], now, message],
            ['student', 'topic', 'status', 'date_created', 'text'])
    except sqlite3.IntegrityError:
        db.close()
        return error('You have already requested this topic!')

    res = db.select_columns('users', ['name', 'email'], ['id'], [supervisor])
    hr_tag = '<hr style="border: 1px dashed;">'
    send_email(to=res[0][1],
               name=res[0][0],
               subject='New Topic Request',
               messages=[
                   'A student has requested a thesis topic on offer by you.',
                   f'The topic is titled "{topic_name}".',
                   f'A message from the student is attached below:{hr_tag}',
                   message.replace('\n', '<br>'),
                   f'{hr_tag}You can approve or reject the topic request ' +
                   f'<a href="{config.SITE_HOME}">here</a>.'
               ])

    db.close()
    return jsonify({'status': 'ok'})
Пример #5
0
def signup():
    if current_user.is_authenticated:
        return render_view(url_for('dashboard'),
                           redirect=True,
                           message=_('SESSIONS_MSG_ALREADY_SIGNED_IN'))

    redirect_to = session.pop('redirect_to', None)

    if request.values.get('ret'):
        redirect_to = request.values.get('ret')

    form = SignUpForm(ret=redirect_to)

    if form.is_submitted():
        try:
            if not form.validate():
                raise Exception(_('ERROR_INVALID_SUBMISSION'))

            if not verify_captcha():
                raise Exception(_('SESSIONS_ERROR_UNFINISHED_CHALLENGE_LBL'))

            # Create user from the form
            user = User.create()

            form.populate_obj(user)
            user.set_password(form.password.data)
            user.last_seen = datetime.datetime.utcnow()
            user.last_login = datetime.datetime.utcnow()

            # store the user
            user.save()

            # Login User
            login_user(user)

            redirect_to = form.back_link.data

            if not redirect_to:
                redirect_to = url_for('dashboard')

            # send registration email
            send_email('registration', user)

            return render_view(redirect_to,
                               redirect=True,
                               message=_('SESSIONS_MSG_SIGNUP_COMPLETED'))
        except Exception as e:
            flash(e.message, 'error')

    return render_view('admin/sessions/signup.html', form=form)
Пример #6
0
def invite_user():
    form = InviteForm()
    # users can only add users one privilege level below them
    form.role.choices = [(role.id, role.title) for role in Role.query.all()
                         if role.level > current_user.roles[0].level]
    if form.validate_on_submit():
        # the method is POST and the form is valid
        token = random_base64(lambda t: Invitation.get(t) is None)
        invitation = Invitation(
            token,
            form.email.data,
            Role.get_by_id(form.role.data),
            current_user
        )

        # invite_link: http://<host>/signup?invite=<token>
        invite_link = url_for('auth.signup', _external=True, invite=token)

        # prepare and send invitation email
        try:
            send_email(
                subject="Asset Tracker Invitation",
                sender=(current_user.name, current_user.email),
                recipients=[form.email.data],
                body="You've been invited to join Asset Tracker. Follow \
                    this link to sign up: %s" % invite_link,
                html="You've been invited to join Asset Tracker. Follow \
                    this link to sign up:<br> <a href=\"%s\">%s</a>" % \
                (invite_link, invite_link)
            )
            db.session.add(invitation)
            db.session.commit()
            flash("Invitation sent to %s" % form.email.data, 'success')
        except Exception, e:
            if current_app.config.get('DEBUG'):
                raise e
            else:
                flash("Failed to send invite due to a %s error"
                      % e.__class__.__name__, 'danger')
                return render_template('auth/invite.html', form=form)

        return redirect(url_for('index'))
def reset_request():

    try:
        fields = ['email_reset']
        email = get_fields(request.form, fields)
        email = email[0]
    except ValueError as e:
        return e.args[0]

    if not re.match(config.EMAIL_FORMAT, email):
        return error(f'Invalid email format!<br>{config.EMAIL_FORMAT_ERROR}')

    db.connect()

    res = db.select_columns('users', ['name', 'id'], ['email'], [email])
    if len(res) == 0:
        db.close()
        return jsonify({'status': 'ok'})

    reset_id = str(uuid.uuid1())

    db.update_rows('users', [reset_id], ['reset_code'], ['id'], [res[0][1]])

    reset_link = url_for('.reset',
                         user=res[0][1],
                         resetID=reset_id,
                         _external=True)
    send_email(
        to=email,
        name=res[0][0],
        subject='Reset Password',
        messages=[
            'You have submitted a request ' + 'to reset your password on TMS.',
            f'Your account is {email}.',
            f'Click <a href="{reset_link}">here</a>' +
            ' to reset your password.'
        ])
    db.close()
    return jsonify({'status': 'ok'})
Пример #8
0
def forgot_password():
    if current_user.is_authenticated:
        return render_view(url_for('latest'),
                           redirect=True,
                           message=_('SESSIONS_MSG_ALREADY_SIGNED_IN'))

    form = ForgotPasswordForm()

    if form.is_submitted():
        try:
            if not form.validate():
                raise Exception(_('ERROR_INVALID_SUBMISSION'))

            if not verify_captcha():
                raise Exception(_('SESSIONS_ERROR_UNFINISHED_CHALLENGE_LBL'))

            email = form.email.data

            user = User.find_by_email(email)

            if not user:
                raise Exception(_('SESSIONS_ERROR_MAIL_NOT_FOUND',
                                  email=email))

            user.generate_reset_password()

            flash(_('SESSIONS_PASSWORD_RESET', email=email))

            # send reset password email
            send_email('reset_password', user)

            return render_view(url_for('sessions.forgot_password'),
                               redirect=True)

        except Exception as e:
            flash(e.message, 'error')

    return render_view('admin/sessions/forgot_password.html', form=form)
def respond_request():
    data = get_fields(request.form, ['response', 'student-id', 'topic'])
    db.connect()

    req_status = 'approved' if data[0] == 'accept' else 'rejected'
    if req_status == 'approved':
        if 'assessor' not in request.form:
            db.close()
            return error('You must specify an assessor')
        db.delete_rows('student_topic', ['student'], [data[1]])
        db.insert_single('student_topic',
                         [data[1], data[2], request.form['assessor']],
                         ['student', 'topic', 'assessor'])

    queries.respond_topic(data[1], data[2], req_status,
                          datetime.now().timestamp())
    res = db.select_columns('users', ['email', 'name'], ['id'], [data[1]])[0]
    student = {'email': res[0], 'name': res[1]}
    topic = db.select_columns('topics', ['name'], ['id'], [data[2]])[0][0]
    db.close()

    send_email(student['email'], student['name'], 'Topic Reply',
               [f'Your topic request for "{topic}" has been {req_status}.'])
    return jsonify({'status': 'ok'})
Пример #10
0
def mark_task():
    if request.method == 'GET':
        task_id = request.args.get('task', None, type=int)
        student_id = request.args.get('student', None, type=int)
        if task_id is None or student_id is None:
            abort(400)
        db.connect()

        if session['id'] not in get_students_staff(student_id):
            db.close()
            abort(403)

        task = build_task(task_id)
        if not task:
            db.close()
            abort(404)

        res = db.select_columns('users', ['name', 'email'], ['id'],
                                [student_id])
        if not res:
            db.close()
            abort(404)
        student = {'id': student_id, 'name': res[0][0], 'email': res[0][1]}

        task_criteria = db.select_columns('task_criteria',
                                          ['id', 'task', 'name', 'max_mark'],
                                          ['task'], [task_id])

        submission = build_student_submission(student_id, task_id)

        marked_feedback = []
        for criteria in task_criteria:
            marked_feedback.append(
                db.select_columns('marks', ['mark', 'feedback'],
                                  ['criteria', 'student', 'marker'],
                                  [criteria[0], student_id, session['id']]))

        task_criteria_id = []
        for criteria in task_criteria:
            task_criteria_id.append(criteria[0])

        task_max = []
        for criteria in task_criteria:
            task_max.append(criteria[3])

        check_if_assessor = db.select_columns('student_topic', ['student'],
                                              ['assessor', 'student'],
                                              [session['id'], student_id])
        is_assessor = False
        if check_if_assessor:
            is_assessor = True
        db.close()

        heading = f"{task['course_name']} - {task['name']}"

        return render_template('task_base.html',
                               topic_request_text=config.TOPIC_REQUEST_TEXT,
                               heading=heading,
                               title=task['name'],
                               taskCriteria=task_criteria,
                               student=student,
                               submission=submission,
                               studentId=student_id,
                               taskCriteriaId=task_criteria_id,
                               taskMax=task_max,
                               markedFeedback=marked_feedback,
                               task=task,
                               marker=True,
                               isAssessor=is_assessor)

    data = json.loads(request.data)
    marks = data['marks']
    feedback = data['feedback']
    task_id = data['taskId']
    student_id = data['studentId']
    task_criteria = data['taskCriteria']
    task_max = data['taskMax']
    db.connect()
    if session['id'] not in get_students_staff(student_id):
        db.close()
        abort(403)

    try:
        check = data['approveCheck']
        if (not check):
            res = db.select_columns('request_statuses', ['id'], ['name'],
                                    ['rejected'])
            db.update_rows('submissions', [res[0][0]], ['status'],
                           ['student', 'task'], [student_id, task_id])
        else:
            res = db.select_columns('request_statuses', ['id'], ['name'],
                                    ['approved'])
            db.update_rows('submissions', [res[0][0]], ['status'],
                           ['student', 'task'], [student_id, task_id])

        marks = [100]

        if feedback[0] == '':
            feedback = [None]

    except KeyError:
        pass

    for i in range(len(marks)):
        try:
            val = int(marks[i])
            if val < 0 or val > 100:
                db.close()
                return error('Marks must be between 0-100')

            if val > task_max[i]:
                db.close()
                return error(f'Mark {val} exceeds max mark of {task_max[i]}')
        except ValueError:
            db.close()
            return error('Please enter an integer value for marks')

    for f in feedback:
        if f == '':
            db.close()
            return error('Please enter some feedback')

    for i in range(len(marks)):
        try:
            db.insert_single('marks', [
                task_criteria[i], student_id, session['id'], marks[i],
                feedback[i]
            ], ['criteria', 'student', 'marker', 'mark', 'feedback'])
        except sqlite3.IntegrityError:
            db.update_rows('marks', [marks[i], feedback[i]],
                           ['mark', 'feedback'],
                           ['criteria', 'student', 'marker'],
                           [task_criteria[i], student_id, session['id']])

    marked_method = db.select_columns('marking_methods', ['id'], ['name'],
                                      ["requires mark"])[0][0]
    is_mark_type = len(
        db.select_columns('tasks', ['id'], ['id', 'marking_method'],
                          [task_id, marked_method]))

    if is_mark_type:
        new_sub_status = "pending mark"
        if queries.is_fully_marked(student_id, task_id):
            new_sub_status = "marked"
        elif queries.is_partially_marked(student_id, task_id):
            new_sub_status = "partially marked"

        status_id = db.select_columns('request_statuses', ['id'], ['name'],
                                      [new_sub_status])[0][0]

        db.update_rows('submissions', [status_id], ['status'],
                       ['student', 'task'], [student_id, task_id])

    # send email
    student = db.select_columns('users', ['name', 'email'], ['id'],
                                [student_id])[0]
    task_name = db.select_columns('tasks', ['name'], ['id'], [task_id])[0][0]
    marker = session['name']
    subject = f'Marks Entered for Task "{task_name}"'
    msg1 = f'Your submission for task "{task_name}"' + \
           f' has just been marked by {marker}.'
    view_link = url_for('.view_task', task=task_id, _external=True)
    msg2 = f'You can view your marks and feedback ' + \
           f'<a href="{view_link}">here</a>.'
    send_email(to=student[1],
               name=student[0],
               subject=subject,
               messages=[msg1, msg2])

    db.close()
    return jsonify({'status': 'ok'})
Пример #11
0
def register():
    if request.method == 'GET':
        return render_template('register.html',
                               title='Register', hide_navbar=True)

    try:
        fields = ['email', 'password', 'confirm-password']
        email, password, confirm = get_fields(request.form, fields)
    except ValueError as e:
        return e.args[0]

    if not re.match(config.EMAIL_FORMAT, email):
        return error(
            f'Invalid email format!<br>{config.EMAIL_FORMAT_ERROR}', 'email')

    db.connect()
    res = db.select_columns('users', ['email', 'date_created', 'confirm_code'],
                            ['email'], [email])

    now = datetime.now().timestamp()
    if len(res):
        if res[0][2] != '' and res[0][1] + config.ACCOUNT_EXPIRY < now:
            # expire unactivated accounts every 24 hours
            db.delete_rows('users', ['email'], [email])
        else:
            db.close()
            return error('This email has already been registered!', 'email')

    if len(password) < 8:
        msg = 'Password must be at least 8 characters long!'
        db.close()
        return error(msg, 'password')

    if password != confirm:
        db.close()
        return error('Passwords do not match!', 'confirm-password')

    hashed_pass = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    name = email.split('@')[0]

    # get the id for a public account
    acc_type = db.select_columns('account_types',
                                 ['id'], ['name'], ['public'])

    confirm_code = uuid.uuid1()
    activation_link = url_for('.confirm', user=name,
                              confirm_code=confirm_code, _external=True)
    send_email(to=email, name=email, subject='Confirm Account Registration',
               messages=[
                   'You recently registered for an account on TMS.',
                   'To activiate your account, click ' +
                   f'<a href="{activation_link}">here</a>.',
                   'This link will expire in 24 hours.'
               ])

    db.insert_single(
        'users',
        [name, hashed_pass, email, acc_type[0][0], str(confirm_code), now],
        ['name', 'password', 'email', 'account_type', 'confirm_code',
         'date_created']
    )
    db.close()
    return jsonify({'status': 'ok'})