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"})
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()))
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
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
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})
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)
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)})
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)
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)
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})
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])
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)
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])
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)
def auth_error(code, headm=None): resp, http_code = error_response(code) if headm: resp.headers['WWW-Authenticate'] = 'Bearer ' + headm return resp, http_code