def add_resource(): """ POST endpoint that adds a new resource link to the club profile. """ user = get_current_user() club = user.club json = g.clean_json res_name = json['name'] res_link = json['link'] new_resource_id = random_slugify(res_name, max_length=100) for resource in club.resources: if resource.id == new_resource_id: raise JsonError(status='error', reason='Resource already exists under that name') resource = Resource( id=new_resource_id, name=res_name, link=res_link ) club.resources += [resource] user.club.last_updated = pst_right_now() user.save() return _fetch_resources_list(user)
def add_question(): """ POST endpoint that adds a new frequently asked question. """ user = get_current_user() club = user.club json = g.clean_json question_statement = json['question'] new_question_id = random_slugify(question_statement, max_length=100) for question in club.faq: if question.id == new_question_id: raise JsonError(status='error', reason='Question already exists') new_question = Question( id = new_question_id, question = question_statement, answer = json['answer'] ) club.faq += [new_question] user.club.last_updated = pst_right_now() user.save() return _fetch_question_list(user)
def modify_gallery_pic(pic_id): """ PUT endpoint that either replaces an existing gallery picture, changes the image's caption or does both at the same time. """ user = get_current_user() json = g.clean_json gallery_pic = user.club.gallery_media.filter(id=pic_id).first() if gallery_pic is None: raise JsonError(status='error', reason='Specified gallery picture does not exist.') new_caption = json.get('caption', None) if new_caption is not None: gallery_pic.caption = new_caption gallery_pic_file = request.files.get('photo', None) if gallery_pic_file is not None: gallery_pic_url, new_pic_id = flask_exts.img_manager.upload_img_asset_s3( user.club.link_name, gallery_pic_file, 'gallery', file_size_limit = 2 * 1024 * 1024 ) gallery_pic.id = new_pic_id gallery_pic.url = gallery_pic_url user.club.last_updated = pst_right_now() user.save() return _fetch_gallery_media_list(user)
def add_gallery_media_pic(): """ POST endpoint that adds a new gallery picture to the club with an image upload and a caption. """ user = get_current_user() json = g.clean_json gallery_pic_file = request.files.get('photo', None) if gallery_pic_file is not None: gallery_pic_url, pic_id = flask_exts.img_manager.upload_img_asset_s3( user.club.link_name, gallery_pic_file, 'gallery', file_size_limit = 2 * 1024 * 1024 ) gallery_pic = GalleryPic( id = pic_id, url = gallery_pic_url, caption = json['caption'] ) user.club.gallery_media += [gallery_pic] user.club.last_updated = pst_right_now() user.save() return _fetch_gallery_media_list(user) else: raise JsonError(status='error', reason='A gallery picture was not provided for uploading.')
def edit_profile(): """ POST endpoint that edits the club profile. """ user = get_current_user() json = g.clean_json for key in json.keys(): if key == 'is_reactivating': continue if key == 'tags': user.club['tags'] = Tag.objects.filter(id__in=json['tags']) elif key == 'num_users': user.club['num_users'] = NumUsersTag.objects.filter(id=json['num_users']).first() elif key == 'social_media_links': user.update(club__social_media_links=json['social_media_links']) else: user.club[key] = json[key] user.club.last_updated = pst_right_now() if json['is_reactivating'] and not user.club.reactivated: user.club.reactivated = True user.club.reactivated_last = user.club.last_updated user.save() return {'status': 'success'}
def add_recruiting_event(): """ POST endpoint that adds a new recruiting event. """ user = get_current_user() club = user.club json = g.clean_json r_event_name = json['name'] new_event_id = random_slugify(r_event_name, max_length=100) for r_event in club.recruiting_events: if r_event.id == new_event_id: raise JsonError(status='error', reason='Recruiting event already exists under that name') new_r_event = RecruitingEvent( id = new_event_id, name = r_event_name, link = json['link'], virtual_link = json['virtual_link'], event_start = json['event_start'], event_end = json['event_end'], description = json['description'], invite_only = json['invite_only'], ) club.recruiting_events += [new_r_event] user.club.last_updated = pst_right_now() user.save() return _fetch_recruiting_events_list(user)
def remove_gallery_media(media_id): """ DELETE endpoint that deletes an existing gallery picture. """ user = get_current_user() user.club.gallery_media = [gallery_media for gallery_media in user.club.gallery_media if gallery_media.id != media_id] user.club.last_updated = pst_right_now() user.save() return _fetch_gallery_media_list(user)
def update_apply_required_or_recruiting_statuses(): """ Update if a club is open for applying or recruiting. """ right_now_dt = pst_right_now() for officer_user in NewOfficerUser.objects: if officer_user.club.app_required and officer_user.club.apply_deadline_start and officer_user.club.apply_deadline_end: apply_deadline_in_range = officer_user.club.apply_deadline_start < right_now_dt and officer_user.club.apply_deadline_end > right_now_dt officer_user.club.new_members = apply_deadline_in_range officer_user.save() elif not officer_user.club.app_required and officer_user.club.recruiting_start and officer_user.club.recruiting_end: recruiting_period_in_range = officer_user.club.recruiting_start < right_now_dt and officer_user.club.recruiting_end > right_now_dt officer_user.club.new_members = recruiting_period_in_range officer_user.save()
def add_event(): """ POST endpoint that adds a new event. """ user = get_current_user() club = user.club json = g.clean_json event_name = json['name'] event_invite_only = json['invite_only'] event_link = json['link'] event_links = json['links'] event_location = json['location'] event_start = json['event_start'] event_end = json['event_end'] event_description = json['description'] event_tags = json['tags'] new_event_id = random_slugify(event_name, max_length=100) for event in club.events: if event.id == new_event_id: raise JsonError(status='error', reason='Event already exists under that name') event = Event( id=new_event_id, invite_only=event_invite_only, name=event_name, link=event_link, links=event_links, location=event_location, event_start=event_start, event_end=event_end, description=event_description, tags=event_tags ) club.events += [event] user.club.last_updated = pst_right_now() user.save() return _fetch_event_list(user)
def delete_question(question_id): """ DELETE endpoint that deletes an existing question. """ user = get_current_user() club = user.club prev_len = len(club.faq) club.faq = [question for question in club.faq if question.id != question_id] user.club.last_updated = pst_right_now() user.save() new_len = len(club.faq) if new_len != prev_len: return _fetch_question_list(user) else: raise JsonError(status='error', reason='Requested question does not exist', status_=404)
def delete_recruiting_event(r_event_id): """ DELETE endpoint that deletes an existing recruiting event. """ user = get_current_user() club = user.club prev_len = len(club.recruiting_events) club.recruiting_events = [r_event for r_event in club.recruiting_events if r_event.id != r_event_id] user.club.last_updated = pst_right_now() user.save() new_len = len(club.recruiting_events) if new_len != prev_len: return _fetch_recruiting_events_list(user) else: raise JsonError(status='error', reason='Requested recruiting event does not exist', status_=404)
def delete_resource(resource_id): """ DELETE endpoint that deletes an existing resource link. """ user = get_current_user() club = user.club prev_len = len(club.resources) club.resources = [resource for resource in club.resources if resource.id != resource_id] user.club.last_updated = pst_right_now() user.save() new_len = len(club.resources) if new_len != prev_len: return _fetch_resources_list(user) else: raise JsonError(status='error', reason='Requested resource does not exist', status_=404)
def update_recruiting_event(r_event_id): """ PUT endpoint that updates an existing recruiting event. """ user = get_current_user() club = user.club json = g.clean_json for (i, r_event) in enumerate(club.recruiting_events): if r_event.id == r_event_id: for key in json.keys(): club.recruiting_events[i][key] = json[key] user.club.last_updated = pst_right_now() user.save() return _fetch_recruiting_events_list(user) raise JsonError(status='error', reason='Requested recruiting event does not exist', status_=404)
def update_resource(resource_id): """ PUT endpoint that updates an existing resource link. """ user = get_current_user() club = user.club json = g.clean_json for (i, resource) in enumerate(club.resources): if resource.id == resource_id: for key in json.keys(): if json.get(key) is not None: club.resources[i][key] = json[key] user.club.last_updated = pst_right_now() user.save() return _fetch_resources_list(user) raise JsonError(status='error', reason='Requested resource does not exist', status_=404)
def confirm_email(token): """ GET endpoint that confirms the new officer user. This endpoint link is normally within the confirmation email. """ club_email = flask_exts.email_verifier.confirm_token( token, 'confirm-email') if club_email is None: raise JsonError(status='error', reason='The confirmation link is invalid.', status_=404) potential_user = NewOfficerUser.objects(email=club_email).first() if potential_user is None: raise JsonError(status='error', reason='The user matching the email does not exist.', status_=404) # First, revoke the given email token flask_exts.email_verifier.revoke_token(token, 'confirm-email') if potential_user.confirmed: return redirect(LOGIN_URL + LOGIN_CONFIRMED_EXT) confirmed_on = pst_right_now() if confirmed_on - potential_user.registered_on > CurrentConfig.CONFIRM_EMAIL_EXPIRY: raise JsonError( status='error', reason= 'The account associated with the email has expired. Please request for a new confirmation email by logging in.' ) # Then, set the user and club to 'confirmed' if it's not done already potential_user.confirmed = True potential_user.confirmed_on = confirmed_on potential_user.save() return redirect(LOGIN_URL + LOGIN_CONFIRMED_EXT)
def upload_logo(): """ POST endpoint that replaces the current club's logo with a new one. Logos must respect a 1:1 aspect ratio (with a default 5% deviation allowed). A 2 MB limit is imposed as well. """ user = get_current_user() logo_file = request.files.get('logo', None) if logo_file is not None: logo_url, _ = flask_exts.img_manager.upload_img_asset_s3( user.club.link_name, logo_file, 'logo', req_aspect_ratio = 1.0, file_size_limit = 2 * 1024 * 1024 ) user.club.last_updated = pst_right_now() user.club.logo_url = logo_url user.save() return {'status': 'success', 'logo-url': user.club.logo_url} else: raise JsonError(status='error', reason='A logo was not provided for uploading.')
def upload_banner(): """ POST endpoint that replaces the current club's banner with a new one. Banners must respect a 10:3 aspect ratio (with a default 5% deviation allowed). A 2 MB limit is imposed as well. """ user = get_current_user() banner_file = request.files.get('banner', None) if banner_file is not None: banner_url, _ = flask_exts.img_manager.upload_img_asset_s3( user.club.link_name, banner_file, 'banner', req_aspect_ratio = 10 / 3, file_size_limit = 10 * 1024 * 1024 ) user.club.last_updated = pst_right_now() user.club.banner_url = banner_url user.save() return {'status': 'success', 'banner-url': user.club.banner_url} else: raise JsonError(status='error', reason='A banner was not provided for uploading.')
def fetch_sign_up_stats(): """ GET endpoint that fetches the sign up statistics for all user account types. """ time_delta = pst_right_now() - datetime.timedelta(weeks=1) history_deltas = [ pst_right_now() - datetime.timedelta(weeks=delay) for delay in range(11) ] # Officer stats num_registered_clubs = NewOfficerUser.objects.count() recent_num_registered_clubs = NewOfficerUser.objects.filter( registered_on__gte=time_delta).count() num_registered_clubs_history = reversed( array_diff([ NewOfficerUser.objects.filter( registered_on__gte=hist_delta).count() for hist_delta in history_deltas ])) num_confirmed_clubs = NewOfficerUser.objects.filter(confirmed=True).count() recent_num_confirmed_clubs = NewOfficerUser.objects.filter( confirmed=True, registered_on__gte=time_delta).count() num_confirmed_clubs_history = reversed( array_diff([ NewOfficerUser.objects.filter( confirmed=True, registered_on__gte=hist_delta).count() for hist_delta in history_deltas ])) num_reactivated_clubs = NewOfficerUser.objects.filter( confirmed=True, club__reactivated=True).count() recent_num_reactivated_clubs = NewOfficerUser.objects.filter( confirmed=True, club__reactivated=True, club__reactivated_last__gte=time_delta).count() num_reactivated_clubs_history = reversed( array_diff([ NewOfficerUser.objects.filter( confirmed=True, club__reactivated=True, club__reactivated_last__gte=hist_delta).count() for hist_delta in history_deltas ])) num_clubs_rso_list = PreVerifiedEmail.objects.count() # Student stats num_students_signed_up = NewStudentUser.objects.count() recent_num_students_signed_up = NewStudentUser.objects.filter( registered_on__gte=time_delta).count() num_confirmed_students = NewStudentUser.objects.filter( confirmed=True).count() recent_num_confirmed_students = NewStudentUser.objects.filter( confirmed=True, registered_on__gte=time_delta).count() return { 'club_admin': { 'main': { 'clubs_registered': num_registered_clubs, 'clubs_confirmed': num_confirmed_clubs, 'clubs_reactivated': num_reactivated_clubs, 'clubs_rso_list': num_clubs_rso_list, }, 'changed': { 'clubs_registered': recent_num_registered_clubs, 'clubs_confirmed': recent_num_confirmed_clubs, 'clubs_reactivated': recent_num_reactivated_clubs, }, 'history': { 'clubs_registered': num_registered_clubs_history, 'clubs_confirmed': num_confirmed_clubs_history, 'clubs_reactivated': num_reactivated_clubs_history, } }, 'student': { 'main': { 'students_signed_up': num_students_signed_up, 'students_confirmed': num_confirmed_students, }, 'changed': { 'students_signed_up': recent_num_students_signed_up, 'students_confirmed': recent_num_confirmed_students } } }