def post(self): user = current_user() if not user or not user.is_admin: return '', 403 school = user.school sponsor_name = api.payload['name'] logo_name = '{}-{}'.format(slugify(sponsor_name, separator='-', to_lower=True), uuid4().hex) try: # TODO: Once you have apscheduler, run this as a delayed job logo = upload_image( data=api.payload['logo'], name=logo_name, location='sponsors/' ) except BaseException: logger.error('Error uploading image to S3') return 'Error uploading provided image', 500 dbi.create(Sponsor, { 'school': school, 'name': sponsor_name, 'logo': logo, 'url': api.payload['url'] }) sponsors = format_sponsors(school.sponsors) return sponsors, 201
def get(self, week_num): user = current_user() if not user: return '', 403 challenges = sorted(user.school.active_challenges(), key=attrgetter('start_date')) curr_week_num = current_week_num(challenges) challenge = challenges[week_num - 1] # If requesting future check_in or # requesting first check_in but challenges haven't started yet, error out if week_num > curr_week_num or ( week_num == 1 and date.today() < challenge.start_date.date()): return '', 403 # Get the CheckIn from the Challenge check_in = challenge.check_in # Get formatted question-answers for this user questions = format_questions(check_in, user) return { 'id': check_in.id, 'challengeName': challenge.name, 'questions': questions }
def put(self): user = current_user() if not user or not user.is_admin: return '', 403 prize = dbi.find_one(Prize, {'id': api.payload['id']}) if not prize: return 'Can\'t find prize to update :/', 500 sponsor = dbi.find_one(Sponsor, {'id': api.payload['sponsorId']}) if not sponsor: return 'Sponsor required to update prize', 500 dbi.update( prize, { 'sponsor': sponsor, 'name': api.payload['name'], 'count': api.payload['count'] or 1 }) prizes = format_prizes(prize.challenge.active_prizes()) return prizes, 200
def post(self): user = current_user() if not user or not user.is_admin: return '', 403 challenge = dbi.find_one(Challenge, {'id': api.payload['challengeId']}) if not challenge: return 'Challenge required to create prize', 500 sponsor = dbi.find_one(Sponsor, {'id': api.payload['sponsorId']}) if not sponsor: return 'Sponsor required to create prize', 500 dbi.create( Prize, { 'challenge': challenge, 'sponsor': sponsor, 'name': api.payload['name'], 'count': api.payload['count'] or 1 }) return format_prizes(challenge.active_prizes())
def get(self, week_index): user = current_user() if not user or not user.is_admin: return '', 403 args = dict(request.args.items()) resp_data = {} if args.get('withWeeks') == 'true': challenges = sorted(user.school.active_challenges(), key=attrgetter('start_date')) weeks = [] i = 0 for c in challenges: weeks.append({ 'title': 'Week {} - {}'.format(i + 1, c.name), 'value': i }) i += 1 resp_data['weeks'] = weeks # Get email template for WeeklyEmail, as well as model attrs. Add to resp_data['week'] resp_data['week'] = {} return resp_data, 200
def put(self): user = current_user() if not user: return '', 403 payload = api.payload or {} check_in_id = payload.get('id') if not check_in_id: return 'CheckInId required to save user\'s answers', 500 questions = payload.get('questions') or [] if not questions: return 'Questions list required to save user\'s answers', 500 check_in = dbi.find_one(CheckIn, {'id': check_in_id}) if not check_in: logger.error('No CheckIn for id: {}'.format(check_in_id)) return 'CheckIn Not Found', 500 for q in questions: question = q.get('question') answer = q.get('answer') if not question or not answer or \ not question.get('id') or not question.get('text') or 'text' not in answer: return 'Invalid question/answer format', 500 answer_id = answer.get('id') # If answer already has been created, find and update it if answer_id: check_in_answer = dbi.find_one(CheckInAnswer, {'id': answer_id}) if not check_in_answer: logger.error( 'No CheckInAnswer for id: {}'.format(answer_id)) return 'Answer doesn\'t exist', 500 dbi.update(check_in_answer, {'text': answer['text']}) else: # otherwise, create a new answer dbi.create( CheckInAnswer, { 'user': user, 'check_in_question_id': question['id'], 'text': answer['text'] }) questions = format_questions(check_in, user) return questions
def get(self): user = current_user() if not user or not user.is_admin: return '', 403 challenges = sorted(user.school.active_challenges(), key=attrgetter('start_date')) data = formatted_winners(challenges) return data
def get(self): user = current_user() if not user or not user.is_admin: return '', 403 challenges = sorted(user.school.active_challenges(), key=attrgetter('start_date')) resp = format_response_overviews(challenges) return resp
def get(self): user = current_user() if not user: return '', 403 challenges = sorted(user.school.active_challenges(), key=attrgetter('start_date')) challenge_ids = [c.id for c in challenges] curr_week_num = current_week_num(challenges) # TODO: Eager-load all of this check_ins = dbi.find_all(CheckIn, {'challenge_id': challenge_ids}) check_ins_map = {c.challenge_id: c for c in check_ins} check_in_answers_map = { a.check_in_question_id: a for a in user.check_in_answers } formatted_check_ins = [] i = 1 for c in challenges: check_in = check_ins_map[c.id] check_in_questions = check_in.check_in_questions num_questions = len(check_in_questions) num_answers = 0 for q in check_in_questions: if check_in_answers_map.get(q.id): num_answers += 1 data = { 'challengeName': c.name, 'weekNum': i, 'numQuestions': num_questions, 'numAnswers': num_answers } formatted_check_ins.append(data) i += 1 launched = True if date.today() < challenges[0].start_date.date(): launched = False return { 'checkIns': formatted_check_ins, 'weekNum': curr_week_num, 'launched': launched }
def get(self): user = current_user() if not user or not user.is_admin: return '', 403 csv_data = format_school_users_csv(user.school) resp = { 'content': csv_data, 'filename': 'all-users.csv' } return resp
def get(self): # How you would validate the request came from an authed user user = current_user() # Error out if unauthorized request if not user: return UNAUTHORIZED # Parse our payload from args payload = dict(request.args.items()) # Get resource return {}, 200
def put(self): user = current_user() if not user or not user.is_admin: return '', 403 try: start_date = datetime.strptime(api.payload['startDate'], '%m/%d/%y') except: return 'Invalid start date', 500 challenge_slugs = [c['slug'] for c in api.payload['challenges']] school = user.school challenges = dbi.find_all(Challenge, { 'school': user.school, 'slug': challenge_slugs }) i = 0 for slug in challenge_slugs: challenge = [c for c in challenges if c.slug == slug][0] if i > 0: start_date = start_date + timedelta(days=7) end_date = start_date + timedelta(days=6) dbi.update(challenge, { 'start_date': start_date, 'end_date': end_date }) i += 1 challenges = sorted(school.active_challenges(), key=attrgetter('start_date')) curr_week_num = current_week_num(challenges) challenges_data = format_challenges(challenges, user, curr_week_num=curr_week_num) resp = {'weekNum': curr_week_num, 'challenges': challenges_data} return resp
def post(self): from_user = current_user() if not from_user: return '', 403 to_email = api.payload['email'] to_user = dbi.find_one(User, {'email': to_email}) if to_user: return 'User already on Quokka', 500 user_mailer.invite_user(from_user, to_email) return '', 200
def put(self): user = current_user() if not user: return '', 403 updates = { 'hashed_pw': auth_util.hash_pw(api.payload['password']) } if user.school.slug == 'rice-university' and api.payload.get('dorm'): updates['meta'] = {'dorm': api.payload['dorm']} dbi.update(user, updates) return '', 200
def put(self): user = current_user() if not user or not user.is_admin: return '', 403 challenge = dbi.find_one(Challenge, {'id': api.payload['id']}) if not challenge: logger.error('No challenge found for id: {}'.format( api.payload['id'])) return 'Challenge required to update text and points', 500 dbi.update(challenge, {'suggestions': api.payload['suggestions']}) return {'suggestions': challenge.suggestions}
def delete(self): user = current_user() if not user or not user.is_admin: return '', 403 args = dict(request.args.items()) prize = dbi.find_one(Prize, {'id': args.get('id')}) if not prize: return 'Can\'t find prize to destroy :/', 500 dbi.destroy(prize) prizes = format_prizes(prize.challenge.active_prizes()) return prizes, 200
def get(self): user = current_user() if not user: return '', 403 # Get challenges for school, sorted by date challenges = sorted(user.school.active_challenges(), key=attrgetter('start_date')) curr_week_num = current_week_num(challenges) challenges_data = format_challenges(challenges, user, curr_week_num=curr_week_num) resp = {'weekNum': curr_week_num, 'challenges': challenges_data} return resp
def get(self, check_in_id): user = current_user() if not user or not user.is_admin: return '', 403 check_in = dbi.find_one(CheckIn, {'id': check_in_id}) if not check_in: return '', 404 include_dorm = user.school.slug == 'rice-university' csv_data = format_csv_responses(check_in, include_dorm=include_dorm) resp = { 'content': csv_data, 'filename': 'check-in-responses-{}.csv'.format(check_in.challenge.slug) } return resp
def post(self): # NOTE: Very aware this endpoint makes a shit-ton of queries and most everything should # be eager loaded, but I don't have time to figure all that syntax bullshit out right now for # properly eager loading. TODO: Refactor this user = current_user() if not user or not user.is_admin: return '', 403 school = user.school challenges = sorted(school.active_challenges(), key=attrgetter('start_date')) # Get challenge to assign winners for challenge = [ c for c in challenges if c.id == api.payload['challenge_id'] ] # Make sure challenge exists... if challenge: challenge = challenge[0] else: return 'Challenge Not Found', 404 # If challenge hasn't started yet, error out if challenge.start_date.date() > date.today(): return '', 401 # Get prizes for this challenge prizes = sorted(dbi.find_all(Prize, {'challenge': challenge}), key=attrgetter('id')) prize_ids = [p.id for p in prizes] # Error out if winners have already been chosen for this challenge if dbi.find_all(Winner, {'prize_id': prize_ids}): return 'Winners already chosen for this challenge', 500 # Get reference to all prizes across all challenges for this school school_prizes = dbi.find_all( Prize, {'challenge_id': [c.id for c in challenges]}) # Get list of all past winners for this school past_winners = [] for p in school_prizes: past_winners += p.winners # Find user_ids for all past winners past_winner_user_ids = [ u.id for u in dbi.find_all( User, {'id': [w.user_id for w in past_winners]}) ] # Get all check_in_question_ids for this check_in and sort them question_ids = [q.id for q in challenge.check_in.check_in_questions] question_ids.sort() # Find ALL check_in_answers related to these check_in_questions answers = dbi.find_all(CheckInAnswer, {'check_in_question_id': question_ids}) # Create a map of user_id to list of check_in_question_ids that they answered for this check_in # Ex: {1: [2, 3, 4]} --> we'll then compare [2, 3, 4] to question_ids to see if they match user_ids_to_question_ids = {} for a in answers: if a.user_id not in user_ids_to_question_ids: user_ids_to_question_ids[a.user_id] = [a.check_in_question_id] else: user_ids_to_question_ids[a.user_id].append( a.check_in_question_id) # Find users who: # (1) haven't been selected as winners in the past # (2) have answered all check_in_questions for this check_in potential_winner_user_ids = [] for k, v in user_ids_to_question_ids.items(): v.sort() if k not in past_winner_user_ids and v == question_ids: potential_winner_user_ids.append(k) if not potential_winner_user_ids: return 'No users currently eligible for prizes -- either everyone has already won or no one has filled out check-ins', 400 potential_winning_users = dbi.find_all( User, { 'id': potential_winner_user_ids, 'is_admin': False # admins can't win }) prize_ids_for_winners = [] for p in prizes: prize_ids_for_winners += ([p.id] * p.count) # Random prize assignment shuffle(prize_ids_for_winners) winning_users = random_subset(potential_winning_users, len(prize_ids_for_winners)) i = 0 for u in winning_users: winner = dbi.create(Winner, { 'user': u, 'prize_id': prize_ids_for_winners[i] }) # Send the winner an email congratulating him/her challenge_mailer.congratulate_winner(challenge, winner.prize, u, school) i += 1 data = formatted_winners(challenges) return data
def get(self, week_num): user = current_user() if not user: return '', 403 school = user.school week_index = week_num - 1 # Get challenges for school, sorted by date challenges = sorted(school.active_challenges(), key=attrgetter('start_date')) if week_num < 1 or week_num > len(challenges): return { 'error': 'Challenge does not exist', 'code': CHALLENGE_NOT_EXIST }, 400 curr_week_num = current_week_num(challenges) # if this is a future week and the user isn't an admin, prevent access if week_num > curr_week_num and not user.is_admin: return { 'error': 'Week not yet available to access', 'code': INVALID_CHALLENGE_ACCESS }, 400 # Find the challenge requested by week index challenge = challenges[week_index] if week_index == 0: prev_habit = None next_habit = {'weekNum': 2, 'name': challenges[1].name} elif week_index == len(challenges) - 1: prev_habit = { 'weekNum': week_index, 'name': challenges[week_index - 1].name } next_habit = None else: prev_habit = { 'weekNum': week_index, 'name': challenges[week_index - 1].name } next_habit = { 'weekNum': week_num + 1, 'name': challenges[week_num].name } # if this is the current week and the user isn't an admin, he/she shouldn't have a link to the next week yet if week_num == curr_week_num and not user.is_admin: next_habit = None universal_challenge = universal_challenge_info.get(challenge.slug) resp = { 'id': challenge.id, 'habit': { 'name': challenge.name, 'slug': challenge.slug, 'icon': universal_challenge['icon'], 'dates': { 'start': datetime.strftime(challenge.start_date, '%m/%d/%Y'), 'end': datetime.strftime(challenge.end_date, '%m/%d/%Y') } }, 'overview': universal_challenge['overview'], 'challenge': { 'text': challenge.text, 'points': challenge.points }, 'prizes': format_prizes(challenge.active_prizes()), 'sponsors': format_sponsors(school.sponsors), 'suggestions': challenge.suggestions, 'adjHabits': { 'prev': prev_habit, 'next': next_habit }, 'links': universal_challenge['links'], 'extraInfo': universal_challenge['extra_info'] } return resp