Example #1
0
def resend_activation():
    """
    Resend the activation token in the user's email.
    returns: 403 if any errors occur. 200 if successful, and user get the
             activation mail resent to him.
    """
    req = request.get_json()

    try:
        user = (User.query
                .filter(User.email == req['email'])
                .one())

        if user.is_active:
            return Error("User is already active", 403)()

        serializer = URLSafeSerializer(app.config['SECRET_KEY'])
        activation_token = serializer.dumps(user.email)

        activation_url = url_for('User.activate_user',
                                 activation_token=activation_token,
                                 _external=True)

        Mail(req['email'],
             subject_data={'name': user.full_name},
             html_data={'token': activation_url},
             text_data={'name': user.full_name},
             template_root=SIGNUP_ACTIVATION
             ).send()

        return ""
    except NoResultFound:
        return Error("User with that email doesnt exist", 403)()
def start_test(test_id):
    """
    Start a test.

    If an existing test_attempt that is not complete exists, it is returned.
    If not, if the user has access to the test, a new test attempt and section
    attempt(s) is created and returned.

    :param testID:
    :return: the id of the test attempt
    """

    try:
        attempt = (
            TestAttempt.query
            # can be made inner join because section attempts should
            # exist if question attempt exists
            .join(TestAttempt.section_attempts).options(
                contains_eager(TestAttempt.section_attempts)).filter(
                    TestAttempt.test_id == test_id).filter(
                        TestAttempt.user_id == current_user.id).one())

        if attempt.is_complete:
            return Error("Test is already completed", 403, "TAC001")()

        sorted_section_attempts = sorted(attempt.section_attempts,
                                         key=lambda x: x.id)

        current_section = (filter(lambda x: x.is_complete == False,
                                  sorted_section_attempts))

        # todo penalize the current_section by the value of
        # Pinger's time.

        current_section_id = list(current_section)[0].section_id

    except NoResultFound:  # didn't find existing attempt, create a new one

        if not Test.user_has_access(current_user, test_id):
            return Error("Purchase the Test", 400)()

        current_section_id = TestAttempt.setup_test_attempt(
            test_id, current_user.id)

    test = (Test.query.filter(Test.id == test_id).options(
        load_only(Test.allow_section_jumps)).one())

    # finally, update the cookie
    string = Pinger.push_data_from_data(
        test_id, current_section_id, test.allow_section_jumps == True,
        datetime.timestamp(datetime.now()) + Pinger.PING_GRACE, 0)

    resp = Response()
    resp.headers["ping"] = string

    AuditLog.log_start_test_event(user_id=current_user.id,
                                  test_id=test_id,
                                  current_section_id=current_section_id)

    return resp
Example #3
0
def add_model():
    """Add a new network model
    """

    # parse the json request
    new_model = Model.from_dict(connexion.request.form)
    try:
        # parse the attached xml files
        req_files = connexion.request.files.getlist("files")
        files = []
        for f in req_files:
            # Validate xml input
            filestr = f.stream.read()
            ElementTree.fromstring(filestr)
            f.stream.seek(0)
            files.append(f.stream)
    except ElementTree.ParseError:
        return Error(code=422, message="Invalid XML files"), 422

    # create cimpy objects
    try:
        cimpy_data = cimpy.cim_import(files, new_model.version)
    except Exception:
        return Error(code=422, message="Invalid CIM files"), 422

    new_id = model_db.put_model(new_model, cimpy_data, files)

    # Return the model as `ModelReply`
    return ModelReply.from_model(new_model, new_id)
def finish_section(testID, sectionID):
    try:
        test_id, section_id, jumps_allowed, _, _ = Pinger.split_pinger_string()
    except:
        return Error("No Pinger", 403)()

    try:

        test_attempt = (TestAttempt.query.filter(
            TestAttempt.test_id == test_id).filter(
                TestAttempt.user_id == current_user.id).filter(
                    TestAttempt.is_complete == False).join(
                        TestAttempt.section_attempts).one())

    except NoResultFound:
        return Error("Data not found", 404)()
        pass

    sorted_section_attempts = sorted(
        test_attempt.section_attempts,
        key=lambda section_attempt: section_attempt.section_id)

    current_section_attempt = list(
        filter(
            lambda section_attempt: section_attempt.section_id == int(
                section_id), sorted_section_attempts))[0]

    section_ids = [section.section_id for section in sorted_section_attempts]

    current_section_idx = section_ids.index(int(section_id))

    should_update = False

    # if there is an actual next section,
    # get its id , and update pinger
    if current_section_idx + 1 < len(section_ids):
        next_section_idx = section_ids[current_section_idx + 1]

        should_update = True

    current_section_attempt.is_complete = True
    db.session.commit()

    if should_update:
        string = Pinger.push_data_from_data(
            test_id, next_section_idx, jumps_allowed,
            datetime.timestamp(datetime.now()) + Pinger.PING_GRACE, 0)
        resp = Response()
        resp.headers["ping"] = string

        return resp
Example #5
0
 def set_key(self, new_key):
     if self.__class__.exists(new_key):
         raise Error('%s with key %s already exists' % (
             self.__class__.__name__, new_key))
     if self.get_key == new_key:
         pass
     del BaseModel.objects[self.__class__][self.get_key()]
     old_key = self.get_key()
     self._set_key(new_key)
     if self.get_key() != new_key:
         raise Error('subclass was expected to change key from %s to %s, '
                     'but key is not %s' % (
                     old_key, new_key, self.get_key()))
     self.save()
Example #6
0
        def wrapped(*args, **kwargs):
            assert len(roles) == 1 and type(roles[0]) is str, \
                "first argument is not a string"

            if not current_user.is_authenticated:
                return Error("Not Logged in", 400)()

            query = UserRoles.query.join(UserRoles.role) \
                .filter(Role.name == roles[0]) \
                .filter(UserRoles.user_id == current_user.id) \
                .exists()

            if not db.session.query(query).scalar():
                return Error("Unauthorized", 403)()
            return f(*args, **kwargs)
def get_tab_change(test_id, date):
    if not Corporate.can_access_test(CookieHelper.get_corporate_id(),
                                     test_id):
        return Error("No access", 403)()

    return (Corporate.get_tab_change(CookieHelper.get_corporate_id(),
                                               test_id, date))
def get_personality_analysis(test_id, date):
    if not Corporate.can_access_test(CookieHelper.get_corporate_id(),
                                     test_id):
        return Error("No access", 403)()

    return (Corporate.get_personality_analysis(CookieHelper.get_corporate_id(),
                                               test_id, date))
def get_overview(test_id, date):
    if not Corporate.can_access_test(CookieHelper.get_corporate_id(),
                                     test_id):
        return Error("No access", 403)()

    return (Corporate.get_test_performance(CookieHelper.get_corporate_id(),
                                           test_id, date))
def get_test_attempt_report(test_id, user_id):
    if (not Corporate.can_access_test(CookieHelper.get_corporate_id(), test_id)
            or not Corporate.can_access_user(CookieHelper.get_corporate_id(),
                                             user_id)
    ):
        return Error("No access", 403)()

    report = (TestAttemptReport
              .query
              .join(TestAttempt,
                    and_(TestAttemptReport.test_attempt_id == TestAttempt.id,
                         TestAttempt.test_id == test_id,
                         TestAttempt.user_id == user_id))
              .one()
              )
    test_attempt = (TestAttempt.query
                    .filter(TestAttempt.test_id == test_id)
                    .filter(TestAttempt.user_id == user_id)
                    .one())

    report = report.todict()
    report['tab_change_count'] = test_attempt.focus_lost_count

    del report['test_attempt_id']
    del report['domain_based_ability']
    del report['paragraph_writing_ability']

    return report
Example #11
0
def export_model(id_):
    """Export model to file

    Returns an archive containing the grid data in CIM formatted files and
    profile files that might have been imported previously.

    :param id: Model id
    :type id: int

    :rtype: file
    """
    model_record = model_db.get_model(id_)

    if isinstance(model_record, model_db.record):
        model_files = model_record.files
        # TODO: Which Profiles? Profile in Request?
        return cimpy.cimexport.generate_xml(
            model.cimobj,
            "cgmes_v2_4_15",
            cimpy.cgmes_v2_4_15.Base.Profile["EQ"],
            ["DI", "EQ", "SV", "TP"],
        )
    else:
        return (
            Error(
                code=404, message="No model with id: " + str(id_) + " found in database"
            ),
            404,
        )
Example #12
0
def get_question_details(testID, sectionID, questionID):
    """
    Get question details for a questionID.
    This requires the test attempt for that user and the test to exist (along
    with section attempts)

    If the question has choices, they will be returned too


    FIXME there is a security vulnerability
    for non jumpable exams, the user may get unauthorized
    access to future sections' question details (that he will be allowed to
    attempt in the future)

    :param testID:
    :param sectionID:
    :param questionID:
    :return:
    """
    try:

        if not Question.does_user_have_access(testID, sectionID, questionID,
                                              current_user.id):
            raise NoResultFound

        question = fetch_question(questionID)


    except NoResultFound:
        return Error("Unable to find data", 403)()

    return question
Example #13
0
def get_question_solutions(testID, sectionID, questionID):
    """
    Get question solutions details for a questionID.
    This requires the test attempt for that user and the test to exist (along
    with section attempts)

    If the question has choices, they will be returned too

    :param testID:
    :param sectionID:
    :param questionID:
    :return:
    """
    try:

        if not TestAttempt.can_user_view_solutions(current_user.id, testID):
            raise NoResultFound

        question = fetch_solutions(questionID)


    except NoResultFound:
        return Error("Unable to find data", 403)()

    return question
Example #14
0
def log():
    log = {
        'url': request.args.get('url'),
        'error': request.args.get('error'),
        'filename': request.args.get('filename'),
        'line': request.args.get('line'),
        'useragent': request.args.get('useragent')
    }

    log['host'] = None
    if log['url'] is not None:
        match = re.findall('^http:\/\/[\w.:-]+', log['url'])
        if match:
            log['host'] = match[0]

    if log['filename'] is not None:
        log['filename'] = log['filename'][:500]

    if log['line'] is not None:
        log['line'] = int(log['line'])

    error = Error(url=log['url'],
                  host=log['host'],
                  error=log['error'],
                  filename=log['filename'],
                  line=log['line'],
                  useragent=log['useragent'])
    error.put()

    response = make_response('{callback}({data})'.format(callback=str(
        request.args.get('callback')),
                                                         data=json.dumps(log)))
    response.mimetype = 'application/json'
    return response
Example #15
0
def log_step_activity(user, new_step_count):
    """
	Log a walking activity containing the number of steps specified in
	new_step_count. Return the new step count (0 if the POST request is
	unsuccessful).

	:param background.models.User user\n
	:param int new_step_count
	"""
    url = "{}/activities.json".format(BASE_URL)
    now = datetime.now()
    params = {
        "activityId": '90013',
        "startTime": now.strftime("%H:%M:%S"),
        "durationMillis": 3600000,
        "date": now.strftime("%Y-%m-%d"),
        "distance": new_step_count,
        "distanceUnit": "steps"
    }
    auth_headers = {"Authorization": "Bearer " + user.fb_token}
    response = requests.post(url, headers=auth_headers, params=params)
    if response != 201:
        return new_step_count
    else:
        error = Error(summary="Couldn't log step activity.",
                      origin="background/fitbit.py, in log_step_activity",
                      message=response.json()["errors"][0]["message"],
                      user=user)
        session.add(error)
        session.commit()
        return 0
Example #16
0
def forgot_password():
    """
    Sends Reset Password link to User's email address. User can change
    his/her password through the link mentioned in the Email. It won't be an
    endpoint, it will be a webpage
    :return: 403 if any errors, else return 200
    """
    req = request.get_json()

    serializer = URLSafeSerializer(app.config['SECRET_KEY'])

    try:
        user = User.query \
            .filter(User.email == req['email']) \
            .filter(User.is_active) \
            .one()

        token = serializer.dumps(req['email'])
        reset_password_link = f"{request.url_root}reset_password?token={token}"

        Mail(user.email,
             subject_data={'name': user.full_name},
             html_data={'token': reset_password_link},
             text_data={'token': reset_password_link},
             template_root=FORGOT_PASSWORD
             ).send()

        return ""
    except NoResultFound:
        return Error('Invalid Email Address', 403)()
Example #17
0
def get_test(testID):
    """
    Get Instruction html of a particular Test.
    This will return the html only if the user has access to a test.

    """

    # left outer join on tests -> orders -> ordertest. if user has a
    # paid order  it will be accessible by test.order.

    try:
        # if not Test.user_has_access(current_user, testID):
        #     raise NoResultFound

        test = (Test.query
                .options(
                load_only(Test.id, Test.name, Test.character, Test.price,
                          Test.instruction_html,
                          Test.type,
                          Test.allow_section_jumps))

                .filter(Test.is_active == 1)
                .filter(Test.id == testID)
                .one())


    except NoResultFound:
        return Error("You do not have access to this test", 403)()

    return test
Example #18
0
 def from_model(cls, model, id) -> 'ModelReply':
     """Converts the Model into a ModelReply
     """
     if model is not None:
         return ModelReply(id, model.name, model.profiles, model.version)
     else:
         return Error(code=404, message="Model not found"), 404
def test(test_id):
    try:
        attempt = (
            TestAttempt.query.join(TestAttempt.section_attempts).join(
                SectionAttempt.question_attempts).options(
                    contains_eager(TestAttempt.section_attempts).load_only(
                        SectionAttempt.section_id, SectionAttempt.is_complete,
                        SectionAttempt.time_spent,
                        SectionAttempt.score).contains_eager(
                            SectionAttempt.question_attempts).load_only(
                                QuestionAttempt.question_id,
                                QuestionAttempt.choice_id,
                                QuestionAttempt.tita_choice,
                                QuestionAttempt.attempt_status,
                                QuestionAttempt.question_id,
                                QuestionAttempt.chosen_language_id,
                                QuestionAttempt.time_spent,
                                QuestionAttempt.score,

                                # todo load this through an api if its too slow
                                QuestionAttempt.long_answer)).
            filter(TestAttempt.test_id == test_id).filter(
                TestAttempt.user_id == current_user.id).one())

    except NoResultFound:
        return Error("Please start the test first", 403)()

    return attempt
Example #20
0
def activate_user(activation_token):
    """
    Activate a particular user, based on activation token.
    This sets the is_active field to true in the db.
    :param activation_token: the token that user should have in email
    :return: 403 if any errors, else redirect to root  , and user is activated
    """
    serializer = URLSafeSerializer(app.config['SECRET_KEY'])

    try:
        email = serializer.loads(
                activation_token
        )
        user = User.query \
            .filter(User.email == email) \
            .one()

        user.is_active = True
        db.session.commit()

        # Mail(user.email,
        #      subject_data={'name': user.full_name},
        #      html_data={'name': user.full_name},
        #      text_data={'name': user.full_name},
        #      template_root=WELCOME_MAIL
        #      ).send()

        activate_user_to_mautic.delay(user.email)

        return redirect(f"{request.url_root}login")

    except (NoResultFound, BadSignature):
        return Error('Invalid Token', 403)()
Example #21
0
def delete_model(model_id):
    """Delete a network model

    :param id: Model id
    :type id: int

    :rtype: Model
    """
    model_bytes = redis_connection.get(model_id)
    if model_bytes != None:
        print("MODEL_BYTES: ", model_bytes)
        model = eval(model_bytes.decode("utf-8"))
        model["id"] = int(model_id)
    else:
        return (
            Error(
                code=404,
                message="Cannot delete model with id: "
                + str(model_id)
                + ", not found in database",
            ),
            404,
        )

    files_len_bytes = redis_connection.get(str(model_id) + "_files_len")
    files_len = int(files_len_bytes.decode("utf-8"))
    redis_connection.delete(str(model_id))
    redis_connection.delete(str(model_id) + "_cimpy")
    redis_connection.delete(str(model_id) + "_files_len")
    for index in range(files_len):
        redis_connection.delete(str(model_id) + "_file_" + str(index))
    redis_connection.srem("models", model_id)
    return model
Example #22
0
def get_corporate(corporate_slug):
    try:
        corporate = Corporate.query \
            .filter(Corporate.slug == corporate_slug) \
            .one()
        return corporate
    except NoResultFound:
        return Error("Invalid Corporate Slug", 400)()
Example #23
0
def error_track():
    d = request.form
    logging.info(request.form)
    Error(msg=d['msg'],
          url=d['url'],
          line=d['line'],
          user=users.get_current_user()).put()
    return 'thanks'
Example #24
0
        def wrapped(*args, **kwargs):

            try:
                if request.json:
                    handle_json(validator)
                elif request.form:
                    handle_form(validator)
                else:
                    return Error(message="Invalid request",
                                 http_code=400)()


            except BaseError as e:
                return Error(message="Invalid request", http_code=400,
                             additional=e.to_primitive())()

            return f(*args, **kwargs)
Example #25
0
 def __setattr__(self, key, value):
     if key == 'server':
         if self.is_user():
             raise Error('user XOR server must be passed to Actor')
         if value.actor:
             raise Error('server already has an actor set')
         self._server = value
         self._server.actor = self
     elif key == 'user':
         if self.is_server():
             raise Error('user XOR server must be passed to Actor')
         if hasattr(value, 'actor'):
             raise Error('user already has an actor set')
         self._user = value
         self._user.actor = self
     else:
         super(BaseModel, self).__setattr__(key, value)
Example #26
0
def create_order():
    """
    Creates Order row. Updates order with Razorpay Order ID. Inserts rows in
    Item tables with the Order ID
    :return: {'id': order.id, 'rp_order_id': razorpay_order_id}
    """
    req = request.get_json()
    test_ids = req['tests'] if req['tests'] is not None else []
    promo = req['promo_code']  # will be null if not present
    total_amount = 0

    promo_id = None
    razorpay_order_id = None  # set to null by default
    tests = Test.query \
        .filter(Test.id.in_(test_ids)) \
        .options(load_only('price')) \
        .all()

    for test in tests:
        total_amount += test.price

    total_amount = max(0, total_amount)

    if promo:
        try:
            promo_amt, promo_id = PromoCode.consume_promo_code(
                promo, current_user.id)
            total_amount -= promo_amt
        except ValueError as e:
            return Error(str(e), 400)()

    order = Order(status=OrderStatusTypes.created,
                  amount=total_amount,
                  promo_code_id=promo_id,
                  user_id=current_user.id)

    db.session.add(order)
    db.session.flush()

    if total_amount > 0:
        razorpay_order_id = Razorpay.create_order(order.id, total_amount)
    else:
        order.status = OrderStatusTypes.paid  # mark free order as paid

    order.rp_order_id = razorpay_order_id

    # This adds rows to OrderTest which is important for User to get
    # access when Payment goes through
    for test in tests:
        test_id = test.id
        order_test = OrderTest(order_id=order.id, test_id=test_id)
        db.session.add(order_test)

    db.session.commit()

    return {'id': order.id, 'rp_order_id': razorpay_order_id}
Example #27
0
def get_promo_codes():
    """
    Returns all available Promo Codes in database
    :return: [promo.todict()]
    """
    try:
        promo_codes = PromoCode.query.all()
        return promo_codes
    except NoResultFound:
        return Error('Invalid Promo Code', 400)()
Example #28
0
 def save(self):
     exists = self.__class__.exists(self.get_key())
     not_self = exists and self.__class__.get(self.get_key()) is not self
     if not_self:
         raise Error('%s with key %s already exists but '
                     'is not the object to be saved' % (
                     self.__class__.__name__, self.get_key()
         ))
     if not self.__class__ in BaseModel.objects:
         BaseModel.objects[self.__class__] = {}
     BaseModel.objects[self.__class__][self.get_key()] = self
Example #29
0
def get_promo_code(code):
    """
    Fetch details based on Promo Code
    :param code:
    :return: promo.todict()
    """
    try:
        promo_code = PromoCode.query.filter(PromoCode.promo_code == code).one()
        return promo_code
    except NoResultFound:
        return Error('Invalid Promo Code', 400)()
Example #30
0
    def __init__(self, name):
        if not self.is_valid_name(name):
            raise Error('Erroneous channel name')

        raw = abnf.parse(name, abnf.channel)
        self.mode = ChannelMode
        self.prefix = raw[0]
        self.id = raw[1] if self.prefix == '!' else None
        self.name = raw[2] if self.prefix == '!' else raw[1]

        self.users = []
        self.topic = None