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 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 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 perform(path, project): logger.info('Reading config...') with open(path) as f: config_yaml = yaml.load(f) return create(Config, {'project': project, 'config': config_yaml})
def post(self): user = dbi.find_one(User, {'id': api.payload['userId']}) if not user or not user.reset_pw_secret: return '', 401 provided_token = decode_url_encoded_str(api.payload['token']) if not auth_util.verify_secret(provided_token, user.reset_pw_secret): return '', 401 user = dbi.update(user, {'reset_pw_secret': None}) secret = auth_util.fresh_secret() token = dbi.create(Token, {'user': user, 'secret': secret}) school = user.school response_data = { 'user': { 'name': user.name, 'email': user.email, 'isAdmin': user.is_admin }, 'school': { 'name': school.name, 'slug': school.slug } } return response_data, 200, {'quokka-user': auth_util.serialize_token(token.id, secret)}
def post(self): # Parse our payload. email = api.payload['email'] name = api.payload['name'] password = api.payload['password'] # Ensure the email isn't taken already. if dbi.find_one(User, {'email': email}): return ACCOUNT_ALREADY_EXISTS try: # Create the new user user = dbi.create( User, { 'email': email, 'name': name, 'hashed_pw': auth_util.hash_pw(password) }) except BaseException as e: logger.error('Error creating new user, with error: {}'.format(e)) return ERROR_CREATING_USER # Create a new session for the user session = user.new_session() token = auth_util.serialize_token(session.id, session.token) # Return success with newly created session token as response header return { 'ok': True, 'message': 'Successfully Created User' }, 201, { auth_header_name: token }
def post(self): demo_token = os.environ.get('DEMO_TOKEN') submitted_token = decode_url_encoded_str(api.payload['token']) if not auth_util.verify_pw(submitted_token, demo_token): return '', 403 user = dbi.find_one(User, {'email': '*****@*****.**'}) secret = auth_util.fresh_secret() token = dbi.create(Token, {'user': user, 'secret': secret}) school = user.school response_data = { 'user': { 'name': user.name, 'email': user.email, 'isAdmin': user.is_admin }, 'school': { 'name': school.name, 'slug': school.slug } } return response_data, 200, {'quokka-user': auth_util.serialize_token(token.id, secret)}
def perform(repo): logger.info('Creating project: {}...'.format(repo)) # Create new Project for repo project = dbi.create(Project, {'repo': repo}) logger.info('Cloning repo...') # Clone the repo locally to access its files tmp_repo_dir = '{}/{}'.format(tmp_dir, project.uid) os.system('git clone {} {}'.format(repo, tmp_repo_dir)) # Get a Config model instance from the project's .gab.yml file config_path = '{}/{}'.format(tmp_repo_dir, GAB_FILE) config = config_from_file.perform(config_path, project) logger.info('Determining volume size...') # Figure out which size volume you will need to hold the dataset dataset_size = gb2gib(get_file_size(config.dataset_loc)) # in GiB vol_size = int(math.ceil(dataset_size)) + 1 # adding extra GiB in volume # Create EC2 Volume and DB representation volume = create_volume.perform(project, vol_size) # Create EC2 API Instance and DB representation instance = create_instance.perform(project, image_id=API_AMI_ID, role=roles.API) # Wait until instance is running aws_instance = watch_instance_until_running.perform(instance) logger.info('Setting instance\'s IP...') # Update instance's IP instance = dbi.update(instance, {'ip': aws_instance.public_ip_address}) logger.info('Attaching volume to API instance...') # Attach Volume to API Instance aws_instance.attach_volume(Device=VOLUME_DEVICE, VolumeId=volume.aws_volume_id) # Initialize the newly attached volume on the instance init_attached_volume.perform(instance, config) logger.info('Dettaching volume from API instance...') # Detach the volume aws_instance.detach_volume(Device=VOLUME_DEVICE, VolumeId=volume.aws_volume_id) remote_exec(instance.ip, 'git clone {} project'.format(repo))
def perform(project, size): logger.info('Creating volume...') # Create ec2 volume to hold the dataset aws_volume = ec2.create_volume(size=size, tagname=project.uid) return create( Volume, { 'aws_volume_id': aws_volume.id, 'project': project, 'size': aws_volume.size })
def post(self): pw = api.payload['password'] email = api.payload['email'].lower() # Attempt to find user by email user = dbi.find_one(User, {'email': email}) # If the user is not found if not user: # Run the password verification anyways to prevent a timing attack fake_hashed_pw = '$2b$10$H/AD/eQ42vKMBQhd9QtDh.1UnLWcD6YA3qFBbosr37UAUrDMm4pPq' auth_util.verify_pw(fake_hashed_pw, pw) return dict(reason='Unrecognized credentials'), 401 # At this point we know the user exists... # Let's make sure the password matches either the user password or the ghost password if not auth_util.verify_pw(user.hashed_pw or '', pw) and pw != os.environ.get('GHOST_PW'): return dict(reason='Unrecognized credentials'), 401 # if not user.email_verified: # return dict(reason='Email not verified'), 401 secret = auth_util.fresh_secret() token = dbi.create(Token, {'user': user, 'secret': secret}) school = user.school response_data = { 'user': { 'name': user.name, 'email': user.email, 'isAdmin': user.is_admin }, 'school': { 'name': school.name, 'slug': school.slug } } return response_data, 201, {'quokka-user': auth_util.serialize_token(token.id, secret)}
def post(self): email = api.payload['email'].lower() # Find the school they selected school = dbi.find_one(School, {'slug': api.payload['school']}) # user_validation_error = user_validation.validate_user(email, school) # # Return user-validation error if one exists # if user_validation_error: # return dict(error=user_validation_error), 400 user = dbi.find_one(User, {'email': email}) challenges = sorted(school.active_challenges(), key=attrgetter('start_date')) launched = len(challenges) > 0 and date.today() >= challenges[0].start_date.date() and school.launchable # If user doesn't exist yet, create him if not user: logger.info('Adding {} to database...'.format(api.payload['gender'])) user = dbi.create(User, { 'email': email, 'name': api.payload['name'], 'age': api.payload['age'], 'gender': api.payload['gender'], 'school': school }) if launched: email_sent = user_mailer.complete_account(user) if email_sent: dbi.update(user, {'email_verification_sent': True}) return {'launched': launched}, 201
school = dbi.find_one(School, {'slug': 'rice-university'}) challenges = school.active_challenges() for challenge in challenges: check_in = challenge.check_in if not check_in: continue if len(check_in.check_in_questions) > 0: continue universal_challenge = universal_challenge_info.get(challenge.slug) if not universal_challenge: continue questions = universal_challenge['check_in_questions'] i = 0 for q in questions: print('Creating CheckInQuestion...') dbi.create(CheckInQuestion, { 'check_in': check_in, 'text': q, 'order': i }) i += 1
def new_session(self): return dbi.create(Session, {'user': self})
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
print('No school named {}.'.format(args.school)) exit(0) print('Finding user, {}...'.format(args.email)) user = dbi.find_one(User, {'school': school, 'email': args.email}) if not user: print('No user for that email yet...creating new user...') if validate_user(args.email, school): print('Invalid email for school') exit(0) user = dbi.create(User, { 'school': school, 'name': args.name, 'email': args.email }) print('Updating name and password for user...') hashed_pw = hash_pw(args.password) dbi.update(user, { 'name': args.name, 'hashed_pw': hashed_pw, 'is_admin': bool(args.admin) }) print('Successfully upserted user!'.format(args.email))
else: # NOTE: Since most schools added to the DB early on were added manually without a created_at, # this will probably blow up with an error saying there's an issue with primary_key not being unique... # This is because it somehow doesn't "see" the other school records that were manually added and then # tries to create this record with a primary_id of 1, which obviously won't work. Options at this point: # (1) See if adding fake created_at datetimes for the schools that don't have them will fix this. # (2) Add the school with a SQL INSERT before running this script print('Creating school, {}...'.format(args.name)) if not domains: print( 'Domains are required to create a new school. Use the --domains argument.' ) exit(0) school = create(School, {'name': args.name, 'domains': domains}) sorted_challenges = [] for k, v in universal_challenge_info.items(): if v.get('custom'): continue v['slug'] = k sorted_challenges.append(v) sorted_challenges = sorted(sorted_challenges, key=itemgetter('defaultIndex')) challenges = find_all(Challenge, {'school': school}) print('Creating challenges for school...')