Beispiel #1
0
def cancel_application(idx):
    """
        cancel the application.
        specify the application id in the URL.
    """
    application = Application.query.get(idx)
    if application is None:
        return error_response(7)  # Not found
    if application.status != "pending":
        # The Application has already fullfilled
        return error_response(10)
    db.session.delete(application)
    db.session.commit()
    return jsonify({"message": "Successful Operation"})
Beispiel #2
0
def get_winners_id(idx):
    """
        Return winners' public_id for 'idx' lottery
    """
    lottery = Lottery.query.get(idx)
    if lottery is None:
        return error_response(7)  # Not found
    if not lottery.done:
        return error_response(12)  # This lottery is not done yet.

    def public_id_generator():
        for app in lottery.application:
            if app.status == 'won':
                yield app.user.public_id
    return jsonify(list(public_id_generator()))
Beispiel #3
0
def test_error_response(client):
    with client.application.app_context():
        resp, http_code = error_response(0)
        resp = resp.get_json()
        assert http_code is not None
        assert 'message' in resp
        assert 'code' in resp
        assert resp['code'] == 0
Beispiel #4
0
def home():
    """
        top page. Require/Check Login
    """
    if 'Content-Type' not in request.headers or \
        request.headers['Content-Type'] == \
            'application/x-www-form-urlencoded':
        data = request.form
    elif request.headers['Content-Type'] == 'application/json':
        data = request.json
    else:
        # Unsupported content type
        return error_response(13)

    if 'id' not in data or 'g-recaptcha-response' not in data:
        return error_response(2)  # Invalid request

    # login flow
    secret_id = data.get('id')
    recaptcha_code = data.get('g-recaptcha-response')
    try:
        user = todays_user(secret_id=secret_id)
    except UserNotFoundError:
        return error_response(3)
    except UserDisabledError:
        return error_response(22)
    if not ip_address(request.remote_addr).is_private:
        secret_key = current_app.config['RECAPTCHA_SECRET_KEY']
        request_uri = f'https://www.google.com/recaptcha/api/siteverify?secret={secret_key}&response={recaptcha_code}'  # noqa: E501
        recaptcha_auth = urlopen(request_uri).read()
        auth_resp = json.loads(recaptcha_auth)
        success = auth_resp['success'] and \
            auth_resp['score'] > current_app.config['RECAPTCHA_THRESHOLD']
    else:
        current_app.logger.warning(
            f'Skipping request from {request.remote_addr}')
        success = True

    if success or user.authority == 'admin':
        token = generate_token({'user_id': user.id})
        return jsonify({
            "message": "Login Successful",
            "token": token.decode()
        })

    return error_response(3)  # Login unsuccessful
Beispiel #5
0
def ids_hash():
    """return sha256 hash of `ids.json` used in background
    """
    try:
        checksum = calc_sha256(current_app.config['ID_LIST_FILE'])
    except FileNotFoundError:
        return error_response(20)  # ID_LIST_FILE not found
    return jsonify({"sha256": checksum})
Beispiel #6
0
def list_classroom(idx):
    """
        return infomation about specified classroom
    """
    classroom = Classroom.query.get(idx)
    if classroom is None:
        return error_response(7)  # Not found
    result = classroom_schema.dump(classroom)[0]
    return jsonify(result)
Beispiel #7
0
def translate_secret_to_public(secret_id):
    """translate secret_id into public_id
        This will used for checking the guests at each classes
    """
    user = User.query.filter_by(secret_id=secret_id).first()
    if not user:
        return error_response(5)  # no such user found
    else:
        return jsonify({"public_id": encode_public_id(user.public_id)})
Beispiel #8
0
def list_lottery(idx):
    """
        return infomation about specified lottery.
    """
    lottery = Lottery.query.get(idx)
    if lottery is None:
        return error_response(7)  # Not found
    result = lottery_schema.dump(lottery)[0]
    return jsonify(result)
Beispiel #9
0
def list_application(idx):
    """
        return infomation about specified application.
    """
    user = User.query.filter_by(id=g.token_data['user_id']).first()
    application = Application.query.filter_by(
        user_id=user.id).filter_by(id=idx).first()
    if application is None:
        return error_response(7)  # Not found
    result = application_schema.dump(application)[0]
    return jsonify(result)
Beispiel #10
0
def check_id(classroom_id, secret_id):
    """return if the user is winner of given classroom
        Args:
            classroom_id (int): target classroom
            secret_id (string): secret id of target user
    """
    user = User.query.filter_by(secret_id=secret_id).first()
    if not user:
        return error_response(5)  # no such user found
    try:
        index = get_prev_time_index()
    except (OutOfHoursError, OutOfAcceptingHoursError):
        return error_response(6)  # not acceptable time
    lottery = Lottery.query.filter_by(classroom_id=classroom_id,
                                      index=index).first()
    application = Application.query.filter_by(user=user,
                                              lottery=lottery).first()
    if not application:
        return error_response(19)  # no application found

    return jsonify({"status": application.status})
Beispiel #11
0
def draw_lottery(idx):
    """
        draw lottery as adminstrator
    """
    lottery = Lottery.query.get(idx)
    if lottery is None:
        return error_response(7)  # Not found

    try:
        # Get time index with current datetime
        index = get_draw_time_index()
    except (OutOfHoursError, OutOfAcceptingHoursError):
        return error_response(6)  # Not acceptable time

    if index != lottery.index:
        return error_response(6)  # Not acceptable time

    winners = draw_one(lottery)

    result = users_schema.dump(winners)
    return jsonify(result[0])
Beispiel #12
0
def results():
    """return HTML file that contains the results of previous lotteries
        This endpoint will be used for printing PDF
        which will be put on the wall.
        whoever access here can get the file. This is not a problem because
        those infomations are public.
    """
    #  1. Get previous time index
    #  2. Get previous lotteries using index
    #  3. Search for caches for those lotteries
    #  4. If cache was found, return it
    #  5. Make 2 public_id lists, based on user's 'kind'('student', 'visitor')
    #  6. Send them to the jinja template
    #  8. Caches that file locally
    #  9. Return file

    def public_id_generator(lottery, kind):
        """return list of winners' public_id for selected 'kind'
            original at: L.336, written by @tamazasa
        """
        for app in lottery.application:
            if app.status == 'won' and app.user.kind == kind:
                yield encode_public_id(app.user.public_id)

    # 1.
    try:
        index = get_prev_time_index()
    except (OutOfHoursError, OutOfAcceptingHoursError):
        return error_response(6)  # not acceptable time
    # 2.
    lotteries = Lottery.query.filter_by(index=index)

    # 5.
    whole_results = {'visitor': [], 'student': []}
    for kind in whole_results.keys():
        for lottery in lotteries:
            public_ids = list(public_id_generator(lottery, kind))
            cl = Classroom.query.get(lottery.classroom_id)
            result = {'classroom': f'{cl.grade}{cl.get_classroom_name()}',
                      'winners': public_ids}
            whole_results[kind].append(result)
    data = {'kinds': [], 'horizontal': 3}
    for key, value in whole_results.items():
        data['kinds'].append({'lotteries': value, 'kind': key})

    # 6.
    env = Environment(loader=FileSystemLoader('api/templates'))
    template = env.get_template('results.html')
    return template.render(data)
Beispiel #13
0
def draw_all_lotteries():
    """
        draw all available lotteries as adminstrator
    """
    try:
        # Get time index with current datetime
        index = get_draw_time_index()
    except (OutOfHoursError, OutOfAcceptingHoursError):
        return error_response(6)  # Not acceptable time

    winners = draw_all_at_index(index)

    flattened = list(chain.from_iterable(winners))
    result = users_schema.dump(flattened)
    return jsonify(result[0])
Beispiel #14
0
def apply_lottery(idx):
    """
        apply to the lottery.
        specify the lottery id in the URL.
        1. check request errors
        2. check whether all group_member's secret_id are correct
        3. check wehter nobody in members made application to the same period
        4. get all `user_id` of members
        5. make application of token's owner
        6. if length of 'group_members' list is 0, goto *8.*
        7. set 'is_rep' to True,
           add 'user_id's got in *3.* to 'group_members' list
        8. make members application based on 'user_id' got in *3.*
        9. return application_id as result
        Variables:
            group_members_secret_id (list of str): list of members' secret_id
            lottery: (Lottery): specified Lottery object
            rep_user (User): token's owner's user object
            group_members (list of User): list of group members' User object
    """
    # 1.
    group_members_secret_id = request.get_json()['group_members']
    lottery = Lottery.query.get(idx)
    if lottery is None:
        return error_response(7)  # Not found
    try:
        current_index = get_time_index()
    except (OutOfHoursError, OutOfAcceptingHoursError):
        # We're not accepting any application in this hours.
        return error_response(14)
    if lottery.index != current_index:
        return error_response(11)  # This lottery is not acceptable now.

    # 2. 3. 4.
    group_members = []
    if len(group_members_secret_id) != 0:
        if len(group_members_secret_id) > 3:
            return error_response(21)
        for sec_id in group_members_secret_id:
            try:
                user = todays_user(secret_id=sec_id)
            except (UserNotFoundError, UserDisabledError):
                return error_response(1)  # Invalid group member secret id
            group_members.append(user)
        for user in group_members:
            previous = Application.query.filter_by(user_id=user.id)
            if any(app.lottery.index == lottery.index and
                   app.lottery.id != lottery.id
                   for app in previous.all()):
                # Someone in the group is
                # already applying to a lottery in this period
                return error_response(8)
            if any(app.lottery.index == lottery.index and
                   app.lottery.id == lottery.id
                   for app in previous.all()):

                # someone in the group is already
                # applying to this lottery
                return error_response(9)

    # 5.
    rep_user = User.query.filter_by(id=g.token_data['user_id']).first()
    previous = Application.query.filter_by(user_id=rep_user.id)
    if any(app.lottery.index == lottery.index and
            app.lottery.id != lottery.id
            for app in previous.all()):
        # You're already applying to a lottery in this period
        return error_response(17)
    if any(app.lottery.index == lottery.index and
            app.lottery.id == lottery.id
            for app in previous.all()):
        # Your application is already accepted
        return error_response(16)
    application = previous.filter_by(lottery_id=lottery.id).first()
    # access DB
    # 6. 7.
    if application:
        result = application_schema.dump(application)[0]
        return jsonify(result)
    else:
        if len(group_members) == 0:
            newapplication = Application(
                lottery_id=lottery.id, user_id=rep_user.id, status="pending")
            db.session.add(newapplication)
            db.session.commit()
            result = application_schema.dump(newapplication)[0]
            return jsonify(result)
        else:
            # 8.
            members_app = [Application(
                    lottery_id=lottery.id, user_id=member.id, status="pending")
                    for member in group_members]

            for application in members_app:
                db.session.add(application)
            db.session.commit()
            rep_application = Application(
                lottery_id=lottery.id, user_id=rep_user.id, status="pending",
                is_rep=True,
                group_members=[group_member(app)
                               for app in members_app])
            db.session.add(rep_application)

    # 9.
    db.session.commit()
    result = application_schema.dump(rep_application)[0]
    return jsonify(result)
Beispiel #15
0
 def auth_error(code, headm=None):
     resp, http_code = error_response(code)
     if headm:
         resp.headers['WWW-Authenticate'] = 'Bearer ' + headm
     return resp, http_code