def mark_notice_route(request, notice_id): """ Mark notice as read or unread. Must be logged in as user, provide a valid ID, and own the notice. Return notice. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401, 'EWoueZr0TYSccUhdNISK3A') notice = get_notice(db_conn, {'id': notice_id}) if not notice: return abort(404, 'xsNPOqJoRw-aUrFo0RhVoA') if notice['user_id'] != current_user['id']: return abort(403, 'xPkb7MYXRIOaI7HeV9U37A') if 'read' not in request['params']: errors = [{ 'name': 'read', 'message': 'You must specify read or unread.', 'ref': 'bvtS4G4jQnaLlVSLyUXjVg', }] elif request['params'].get('read') is True: notice, errors = mark_notice_as_read(db_conn, notice) elif request['params'].get('read') is False: notice, errors = mark_notice_as_unread(db_conn, notice) if errors: return 400, { 'errors': errors, 'ref': 'FeEtTWJJQv22dTpz8y5fZA', } return 200, {'notice': deliver_notice(notice, access='private')}
def get_follows_route(request): """ Get a list of the users follows. """ db_conn = request['db_conn'] current_user = get_current_user(request) user_id = request['params'].get('user_id') if user_id: user = get_user(db_conn, {'id': user_id}) if not user: return abort(404, 'sYkDuhNmReOrKyR0xsBmHg') if (user != current_user and user['settings']['view_follows'] != 'public'): return abort(403, 'FnH15Y3MRma6bU2gXqzjQQ') else: user = current_user if not user: return abort(401, 'YMC5rhI1TOCgUQu6jJeoQg') params = dict(**request['params']) params['user_id'] = user['id'] follows = list_follows_by_user(db_conn, params) return 200, { 'follows': [deliver_follow(follow, access='private') for follow in follows] }
def get_card_route(request, card_id): """ Get a specific card given an ID. Show all relevant data, but not used for the learning interface. """ card = get_card_by_kind(card_id) if not card: return abort(404) unit = Unit.get_latest_accepted(entity_id=card['unit_id']) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = Topic.list_by_entity_id(entity_id=card_id) versions = Card.get_versions(entity_id=card_id) requires = Card.list_requires(entity_id=card_id) required_by = Card.list_required_by(entity_id=card_id) params = CardParameters.get(entity_id=card_id) return 200, { 'card': card.deliver(access='view'), 'card_parameters': params.get_values(), 'unit': unit.deliver(), 'topics': [topic.deliver() for topic in topics], 'versions': [version.deliver() for version in versions], 'requires': [require.deliver() for require in requires], 'required_by': [require.deliver() for require in required_by], }
def mark_notice_route(request, notice_id): """ Mark notice as read or unread. Must be logged in as user, provide a valid ID, and own the notice. Return notice. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) notice = get_notice({'id': notice_id}, db_conn) if not notice: return abort(404) if notice['user_id'] != current_user['id']: return abort(403) if 'read' not in request['params']: errors = [{ 'name': 'read', 'message': 'You must specify read or unread.', }] elif request['params'].get('read') is True: notice, errors = mark_notice_as_read(notice, db_conn) elif request['params'].get('read') is False: notice, errors = mark_notice_as_unread(notice, db_conn) if len(errors): return 400, { 'errors': errors, 'ref': 'qR4CBtcfcYfWDTqK9JOXXLhO', } return 200, {'notice': deliver_notice(notice, access='private')}
def remove_subject_route(request, user_id, subject_id): """ Remove a subject from the learner's list of subjects. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401, 'DHlX2XTsTO-1Hhfr9GXkJw') if user_id != current_user['id']: return abort(403, '8yt2d8K1RNKidGIVU1CaOA') user_subjects = list_user_subjects(db_conn, user_id) if not user_subjects: return 404, { 'errors': [{ 'name': 'user_id', 'message': 'User does not have subjects.', 'ref': 'nttevgwMRsOwiT_ul0SmHQ', }], } matches = [ us for us in user_subjects if (convert_slug_to_uuid(us['subject_id']) == convert_slug_to_uuid(subject_id)) ] if not matches: return abort(404, 'AQV0c9qfSdO7Ql2IC8l0bw') errors = remove_user_subject(db_conn, user_id, subject_id) if errors: return 400, { 'errors': errors, 'ref': 'h1BKySSTT0SgH2OTTnSVlA' } return 200, {}
def get_card_route(request, card_id): """ Get a specific card given an ID. Show all relevant data, but not used for the learning interface. """ db_conn = request['db_conn'] card = get_latest_accepted_card(db_conn, card_id) if not card: return abort(404, 'fPebfwqfRNmOiSWqWISeaA') unit = get_latest_accepted_unit(db_conn, card['unit_id']) if not unit: return abort(404, 'IKSqfvHvRK6hbSAIOkQuLg') # TODO-2 SPLITUP create new endpoints for these instead requires = list_required_cards(db_conn, card_id) required_by = list_required_by_cards(db_conn, card_id) params = get_card_parameters(db_conn, {'entity_id': card_id}) return 200, { 'card': deliver_card(card, access='view'), 'card_parameters': (get_card_parameters_values(params) if params else None), 'unit': deliver_unit(unit), 'requires': [deliver_card(require) for require in requires], 'required_by': [deliver_card(require) for require in required_by], }
def get_user_sets_route(request, user_id): """ Get the list of sets the user has added. NEXT STATE GET Choose Set -> POST Choose Set """ current_user = get_current_user(request) if not current_user: return abort(401) if user_id != current_user['id']: return abort(403) next_ = { 'method': 'POST', 'path': '/s/users/{user_id}/sets/{set_id}'.format(user_id=current_user['id'], set_id='{set_id}'), } current_user.set_learning_context(next=next_) uset = UserSets.get(user_id=user_id) if not uset: return 200, {'sets': [], 'next': next_} return 200, { 'sets': [s.deliver() for s in uset.list_sets(**request['params'])], 'next': next_, }
def learn_card_route(request, card_id): """ Render the card's data, ready for learning. NEXT STATE GET Learn Card -> POST Respond Card """ current_user = get_current_user(request) if not current_user: return abort(401) card = get_card_by_kind(card_id) if not card: return abort(404) # Make sure the current unit id matches the card context = current_user.get_learning_context() if context.get('unit', {}).get('entity_id') != card['unit_id']: return abort(400) next_ = { 'method': 'POST', 'path': '/s/cards/{card_id}/responses' .format(card_id=card['entity_id']) } current_user.set_learning_context(card=card.data, next=next_) return 200, { 'card': card.deliver(access=''), 'set': context.get('set'), 'unit': context.get('unit'), 'next': next_, }
def update_topic_route(request, topic_id): """ Update the topic. - Only the name can be changed. - Only by original author. """ current_user = get_current_user(request) if not current_user: return abort(401) # ## STEP 1) Find existing topic instance ## # topic = Topic.get(id=topic_id) if not topic: return abort(404) if topic['user_id'] != current_user['id']: return abort(403) # ## STEP 2) Limit the scope of changes ## # topic_data = request['params']['topic'] topic_data = pick(topic_data, ('name',)) # ## STEP 3) Validate and save topic instance ## # topic, errors = topic.update(topic_data) if errors: errors = prefix_error_names('topic.', errors) return 400, { 'errors': errors, 'ref': 'k7ItNedf0I0vXfiIUcDtvHgQ', } # ## STEP 4) Return response ## # return 200, {'topic': topic.deliver()}
def remove_subject_route(request, user_id, subject_id): """ Remove a subject from the learner's list of subjects. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) if user_id != current_user['id']: return abort(403) user_subject = get_user_subjects(user_id, db_conn) if not user_subject: return 404, { 'errors': [{ 'message': 'User does not have subjects.' }], 'ref': '8huZbvEAYOP8LcZb2sXbqNOC' } if subject_id not in user_subject['subject_ids']: return abort(404) user_subject, errors = remove_user_subjects(user_id, subject_id, db_conn) if errors: return 400, {'errors': errors, 'ref': 'qIfll1e7dbP9V9jmC8FkCwsa'} return 200, {'subjects': user_subject['subject_ids']}
def get_card_route(request, card_id): """ Get a specific card given an ID. Show all relevant data, but not used for the learning interface. """ db_conn = request['db_conn'] card = get_card_by_kind(db_conn, card_id) if not card: return abort(404) unit = Unit.get_latest_accepted(db_conn, entity_id=card['unit_id']) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = list_topics_by_entity_id(card_id, {}, db_conn) versions = Card.get_versions(db_conn, entity_id=card_id) requires = Card.list_requires(db_conn, entity_id=card_id) required_by = Card.list_required_by(db_conn, entity_id=card_id) params = get_card_parameters({'entity_id': card_id}, db_conn) return 200, { 'card': card.deliver(access='view'), 'card_parameters': (get_card_parameters_values(params) if params else None), 'unit': unit.deliver(), 'topics': [deliver_topic(topic) for topic in topics], 'versions': [version.deliver() for version in versions], 'requires': [require.deliver() for require in requires], 'required_by': [require.deliver() for require in required_by], }
def remove_set_route(request, user_id, set_id): """ Remove a set from the learner's list of sets. """ current_user = get_current_user(request) if not current_user: return abort(401) if user_id != current_user['id']: return abort(403) uset = UserSets.get(user_id=user_id) if not uset: return 404, { 'errors': [{ 'message': 'User does not have sets.' }], 'ref': '8huZbvEAYOP8LcZb2sXbqNOC' } if set_id not in uset['set_ids']: return abort(404) uset['set_ids'].remove(set_id) usets, errors = uset.save() if errors: return 400, {'errors': errors, 'ref': 'qIfll1e7dbP9V9jmC8FkCwsa'} return 200, {'sets': uset['set_ids']}
def get_user_sets_route(request, user_id): """ Get the list of sets the user has added. NEXT STATE GET Choose Set -> POST Choose Set """ current_user = get_current_user(request) if not current_user: return abort(401) if user_id != current_user['id']: return abort(403) next_ = { 'method': 'POST', 'path': '/s/users/{user_id}/sets/{set_id}' .format(user_id=current_user['id'], set_id='{set_id}'), } current_user.set_learning_context(next=next_) uset = UserSets.get(user_id=user_id) if not uset: return 200, {'sets': [], 'next': next_} return 200, { 'sets': [s.deliver() for s in uset.list_sets(**request['params'])], 'next': next_, }
def learn_card_route(request, card_id): """ Render the card's data, ready for learning. NEXT STATE GET Learn Card -> POST Respond Card """ current_user = get_current_user(request) if not current_user: return abort(401) card = get_card_by_kind(card_id) if not card: return abort(404) # Make sure the current unit id matches the card context = current_user.get_learning_context() if context.get('unit', {}).get('entity_id') != card['unit_id']: return abort(400) next_ = { 'method': 'POST', 'path': '/s/cards/{card_id}/responses'.format(card_id=card['entity_id']) } current_user.set_learning_context(card=card.data, next=next_) return 200, { 'card': card.deliver(access=''), 'set': context.get('set'), 'unit': context.get('unit'), 'next': next_, }
def remove_set_route(request, user_id, set_id): """ Remove a set from the learner's list of sets. """ current_user = get_current_user(request) if not current_user: return abort(401) if user_id != current_user['id']: return abort(403) uset = UserSets.get(user_id=user_id) if not uset: return 404, { 'errors': [{'message': 'User does not have sets.'}], 'ref': '8huZbvEAYOP8LcZb2sXbqNOC' } if set_id not in uset['set_ids']: return abort(404) uset['set_ids'].remove(set_id) usets, errors = uset.save() if errors: return 400, { 'errors': errors, 'ref': 'qIfll1e7dbP9V9jmC8FkCwsa' } return 200, {'sets': uset['set_ids']}
def update_topic_route(request, topic_id): """ Update the topic. - Only the name can be changed. - Only by original author. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401, 'ZUiN62FFR3OcBM6s8UJSmg') # ## STEP 1) Find existing topic instance ## # topic = get_topic(db_conn, {'id': topic_id}) if not topic: return abort(404, 'MXzNqBU6SN28tNtRXW9rNw') if topic['user_id'] != current_user['id']: return abort(403, 'MZZbJNt3RK-4kVMo2rROWA') # ## STEP 2) Validate and save topic instance ## # topic_data = request['params'] topic, errors = update_topic(db_conn, topic, topic_data) if errors: return 400, { 'errors': errors, 'ref': 'zu7VABcJT5qCzF7BHNCH5w', } # ## STEP 3) Return response ## # return 200, {'topic': deliver_topic(topic)}
def update_post_route(request, topic_id, post_id): """ Update an existing post. Must be one's own post. For post: - Only the body field may be changed. For proposals: - Only the name, body, and status fields can be changed. - The status can only be changed to declined, and only when the current status is pending or blocked. For votes: - The only fields that can be updated are body and response. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) # ## STEP 1) Find existing post instance ## # post_ = get_post_facade(db_conn, post_id) if not post_: return abort(404) if post_['user_id'] != current_user['id']: return abort(403) post_kind = post_['kind'] # ## STEP 2) Limit the scope of changes ## # post_data = request['params']['post'] if post_kind is 'post': post_data = pick(post_data, ('body',)) elif post_kind is 'proposal': post_data = pick(post_data, ('name', 'body', 'status',)) if (post_data.get('status') != 'declined' or post_data.get('status') not in ('pending', 'blocked',)): del post_data['status'] elif post_kind is 'vote': post_data = pick(post_data, ('body', 'response',)) # ## STEP 3) Validate and save post instance ## # post_, errors = post_.update(db_conn, post_data) if errors: errors = prefix_error_names('post.', errors) return 400, { 'errors': errors, 'ref': 'E4LFwRv2WEJZks7use7TCpww' } # ## STEP 4) Make updates based on proposal / vote status ## # if post_kind == 'proposal': update_entity_status(db_conn, post_) if post_kind == 'vote': proposal = Proposal.get(db_conn, id=post_['replies_to_id']) update_entity_status(db_conn, proposal) # ## STEP 5) Return response ## # return 200, {'post': post_.deliver()}
def update_topic_route(request, topic_id): """ Update the topic. - Only the name can be changed. - Only by original author. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) # ## STEP 1) Find existing topic instance ## # topic = get_topic({'id': topic_id}, db_conn) if not topic: return abort(404) if topic['user_id'] != current_user['id']: return abort(403) # ## STEP 2) Limit the scope of changes ## # topic_data = request['params']['topic'] topic_data = pick(topic_data, ('name', )) # ## STEP 3) Validate and save topic instance ## # topic, errors = update_topic(topic, topic_data, db_conn) if errors: errors = prefix_error_names('topic.', errors) return 400, { 'errors': errors, 'ref': 'k7ItNedf0I0vXfiIUcDtvHgQ', } # ## STEP 4) Return response ## # return 200, {'topic': deliver_topic(topic)}
def choose_unit_route(request, subject_id, unit_id): """ Updates the learner's information based on the unit they have chosen. NEXT STATE POST Chosen Unit -> GET Learn Card """ # TODO-3 simplify this method. should it be broken up or moved to model? db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401, 'NcrRkqIlSW-BkcWLBkwORQ') unit = get_latest_accepted_unit(db_conn, unit_id) if not unit: return abort(404, 'PIti_qwAQ7WXwQwNZertxw') # If the unit isn't in the subject... context = get_learning_context(current_user) subject_ids = [ convert_uuid_to_slug(subject['entity_id']) for subject in list_subjects_by_unit_recursive(db_conn, unit_id) ] context_subject_id = context.get('subject', {}).get('entity_id') if context_subject_id not in subject_ids: return 400, { 'errors': [{ 'message': 'Unit not in subject.', 'ref': 'r32fH0eCRZCivJoh-hKwZQ', }] } # Or, the unit doesn't need to be learned... status = judge(db_conn, unit, current_user) if status == "done": return 400, { 'errors': [{ 'message': 'Unit not needed.', 'ref': 'YTU27E63Rfiy3Rqmqd6Bew', }] } # Choose a card for the learner to learn card = choose_card(db_conn, current_user, unit) if card: next_ = { 'method': 'GET', 'path': '/s/cards/{card_id}/learn'.format( card_id=convert_uuid_to_slug(card['entity_id'])), } else: next_ = {} set_learning_context(current_user, unit=unit, card=card if card else None, next=next_) return 200, {'next': next_}
def choose_unit_route(request, set_id, unit_id): """ Updates the learner's information based on the unit they have chosen. NEXT STATE POST Chosen Unit -> GET Learn Card """ # TODO-3 simplify this method. should it be broken up or moved to model? db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) unit = Unit.get_latest_accepted(db_conn, unit_id) if not unit: return abort(404) # If the unit isn't in the set... context = get_learning_context(current_user) set_ids = [set_['entity_id'] for set_ in Set.list_by_unit_id(db_conn, unit_id)] if context.get('set', {}).get('entity_id') not in set_ids: return abort(400) status = judge(db_conn, unit, current_user) # Or, the unit doesn't need to be learned... if status == "done": return abort(400) # Choose a card for the learner to learn card = choose_card(db_conn, current_user, unit) if card: next_ = { 'method': 'GET', 'path': '/s/cards/{card_id}/learn' .format(card_id=card['entity_id']), } else: next_ = {} set_learning_context( current_user, unit=unit.data, card=card.data if card else None, next=next_ ) return 200, {'next': next_}
def choose_unit_route(request, subject_id, unit_id): """ Updates the learner's information based on the unit they have chosen. NEXT STATE POST Chosen Unit -> GET Learn Card """ # TODO-3 simplify this method. should it be broken up or moved to model? db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) unit = Unit.get_latest_accepted(db_conn, unit_id) if not unit: return abort(404) # If the unit isn't in the subject... context = get_learning_context(current_user) subject_ids = [ subject['entity_id'] for subject in Subject.list_by_unit_id(db_conn, unit_id) ] if context.get('subject', {}).get('entity_id') not in subject_ids: return abort(400) status = judge(db_conn, unit, current_user) # Or, the unit doesn't need to be learned... if status == "done": return abort(400) # Choose a card for the learner to learn card = choose_card(db_conn, current_user, unit) if card: next_ = { 'method': 'GET', 'path': '/s/cards/{card_id}/learn'.format(card_id=card['entity_id']), } else: next_ = {} set_learning_context(current_user, unit=unit.data, card=card.data if card else None, next=next_) return 200, {'next': next_}
def list_units_route(request): """ Return a collection of units by `entity_id`. """ db_conn = request['db_conn'] entity_ids = request['params'].get('entity_ids') if not entity_ids: return abort(404, 'Jxs1KZP-TpilXZ-7f-AYvw') entity_ids = entity_ids.split(',') units = list_latest_accepted_units(db_conn, entity_ids) if not units: return abort(404, 'qR6uk5uZQimx-5mutK5t2g') return 200, {'units': [deliver_unit(unit, 'view') for unit in units]}
def create_password_route(request, user_id): """ Update a user's password if the token is valid. """ user = User.get(id=user_id) if not user: return abort(404) valid = user.is_valid_token(request['params'].get('token')) if not valid: return abort(403) user['password'] = request['params'].get('password') user.save() return _log_in(user)
def list_cards_route(request): """ Return a collection of cards by `entity_id`. """ db_conn = request['db_conn'] entity_ids = request['params'].get('entity_ids') if not entity_ids: return abort(404, 'ESKDY5E7QA6tIpAv9i6WMw') entity_ids = entity_ids.split(',') cards = list_latest_accepted_cards(db_conn, entity_ids) if not cards: return abort(404, 's0uGKuNDSJK00pJs-x1AAQ') return 200, {'cards': [deliver_card(card, 'view') for card in cards]}
def create_topic_route(request): """ """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) user_id = current_user['id'] if user_id != "NNKkHsjE3pEOW0wsPaQJm9MD": return abort(403) data = request['params'] if not data: return abort(404) for key, unit in data.get('units').items(): unit_entity_id, unit_version_id = inject_unit(unit, db_conn) topic_id = inject_topic('unit', unit, unit_entity_id, user_id, db_conn) proposal_id = inject_proposal('unit', unit, user_id, topic_id, unit_version_id, db_conn) inject_votes(topic_id, proposal_id, db_conn) update_status('unit', unit_version_id, db_conn) for card in unit.get('video', []): kind = 'video' entity_id, version_id = inject_video_card(unit_entity_id, card, db_conn) topic_id = inject_topic(kind, card, entity_id, user_id, db_conn) proposal_id = inject_proposal(kind, card, user_id, topic_id, version_id, db_conn) inject_votes(topic_id, proposal_id, db_conn) update_status('card', version_id, db_conn) for card in unit.get('choice', []): kind = 'choice' entity_id, version_id = inject_choice_card(unit_entity_id, card, db_conn) topic_id = inject_topic(kind, card, entity_id, user_id, db_conn) proposal_id = inject_proposal(kind, card, user_id, topic_id, version_id, db_conn) inject_votes(topic_id, proposal_id, db_conn) update_status('card', version_id, db_conn) return 200, 'OK'
def get_unit_route(request, unit_id): """ Get a specific unit given an ID. """ db_conn = request['db_conn'] unit = Unit.get_latest_accepted(db_conn, unit_id) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = list_topics_by_entity_id(unit_id, {}, db_conn) versions = Unit.get_versions(db_conn, unit_id) requires = Unit.list_requires(db_conn, unit_id) required_by = Unit.list_required_by(db_conn, unit_id) sets = Set.list_by_unit_id(db_conn, unit_id) return 200, { 'unit': unit.deliver(), # 'unit_parameters': unit.fetch_parameters(), 'topics': [deliver_topic(topic) for topic in topics], 'versions': [version.deliver() for version in versions], 'requires': [require.deliver() for require in requires], 'required_by': [require.deliver() for require in required_by], 'belongs_to': [set_.deliver() for set_ in sets], }
def list_subjects_route(request): """ Return a collection of subjects by `entity_id`. """ db_conn = request['db_conn'] entity_ids = request['params'].get('entity_ids') if not entity_ids: return abort(404, 'COhZEG0GTW6L2bPh6AYsfw') entity_ids = entity_ids.split(',') subjects = list_latest_accepted_subjects(db_conn, entity_ids) if not subjects: return abort(404, 'ZlLFtBwdS-Sj49ASUoGPZw') return 200, { 'subjects': [deliver_subject(subject, 'view') for subject in subjects] }
def get_unit_route(request, unit_id): """ Get a specific unit given an ID. """ db_conn = request["db_conn"] unit = Unit.get_latest_accepted(db_conn, unit_id) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = Topic.list_by_entity_id(db_conn, unit_id) versions = Unit.get_versions(db_conn, unit_id) requires = Unit.list_requires(db_conn, unit_id) required_by = Unit.list_required_by(db_conn, unit_id) sets = Set.list_by_unit_id(db_conn, unit_id) return ( 200, { "unit": unit.deliver(), # 'unit_parameters': unit.fetch_parameters(), "topics": [topic.deliver() for topic in topics], "versions": [version.deliver() for version in versions], "requires": [require.deliver() for require in requires], "required_by": [require.deliver() for require in required_by], "belongs_to": [set_.deliver() for set_ in sets], }, )
def follow_route(request): """ Follow a card, unit, or set. """ # TODO-3 simplify this method. does some of this belong in the model? db_conn = request["db_conn"] current_user = get_current_user(request) if not current_user: return abort(401) follow_data = dict(**request["params"]) follow_data["user_id"] = current_user["id"] follow = Follow(follow_data) errors = follow.validate(db_conn) if errors: return 400, {"errors": errors, "ref": "4Qn9oWVWiGKvXSONQKHSy1T6"} follow, errors = follow.save(db_conn) if errors: return 400, {"errors": errors, "ref": "gKU6wgTItxpKyDs0eAlonCmi"} return 200, {"follow": follow.deliver(access="private")}
def get_unit_route(request, unit_id): """ Get a specific unit given an ID. """ unit = Unit.get_latest_accepted(unit_id) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = Topic.list_by_entity_id(unit_id) versions = Unit.get_versions(unit_id) requires = Unit.list_requires(unit_id) required_by = Unit.list_required_by(unit_id) sets = Set.list_by_unit_id(unit_id) return 200, { 'unit': unit.deliver(), # 'unit_parameters': unit.fetch_parameters(), 'topics': [topic.deliver() for topic in topics], 'versions': [version.deliver() for version in versions], 'requires': [require.deliver() for require in requires], 'required_by': [require.deliver() for require in required_by], 'belongs_to': [set_.deliver() for set_ in sets], }
def create_password_route(request, user_id): """ Update a user's password if the token is valid. """ db_conn = request['db_conn'] user = get_user({'id': user_id}, db_conn) if not user: return abort(404) token = request['params'].get('token') valid = is_valid_token(user, token) if not valid: return abort(403) given_password = request['params'].get('password') update_user_password(user, {'password': given_password}, db_conn) return _log_in(user)
def next_route(request): """ Tell the learner where to go next. TODO-3 should we move all `next` data from individual endpoints to this one, and have the UI call this endpoint each time to get the next state? """ current_user = get_current_user(request) if not current_user: return abort(401) context = get_learning_context(current_user) # If 'next' action, return that, # else 'next' is GET Choose Subject if context.get('next'): return 200, {'next': context['next']} return 200, { 'next': { 'method': 'GET', 'path': '/s/users/{user_id}/subjects'.format( user_id=convert_uuid_to_slug(current_user['id'])), } }
def get_follows_route(request): """ Get a list of the users follows. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) params = dict(**request['params']) params['user_id'] = current_user['id'] follows = list_follows(params, db_conn) output = { 'follows': [deliver_follow(follow, access='private') for follow in follows] } # TODO-3 SPLITUP should this be a different endpoint? if 'entities' in request['params']: entities = flush_entities(db_conn, [follow['entity'] for follow in follows]) output['entities'] = [ entity.deliver() if entity else None for entity in entities ] return 200, output
def next_route(request): """ Tell the learner where to go next. TODO-3 should we move all `next` data from individual endpoints to this one, and have the UI call this endpoint each time to get the next state? """ current_user = get_current_user(request) if not current_user: return abort(401) context = current_user.get_learning_context() # If 'next' action, return that, # else 'next' is GET Choose Set if context.get('next'): return 200, { 'next': context['next'] } return 200, { 'next': { 'method': 'GET', 'path': '/s/users/{user_id}/sets' .format(user_id=current_user['id']), } }
def get_user_route(request, user_id): """ Get the user by their ID. """ db_conn = request["db_conn"] user = get_user({"id": user_id}, db_conn) current_user = get_current_user(request) # Posts if in request params # Sets if in request params and allowed # Follows if in request params and allowed if not user: return abort(404) data = {} data["user"] = deliver_user(user, access="private" if current_user and user["id"] == current_user["id"] else None) # TODO-2 SPLITUP create new endpoints for these instead if "posts" in request["params"]: data["posts"] = [post.deliver() for post in get_posts_facade(db_conn, user_id=user["id"])] if "sets" in request["params"] and user["settings"]["view_sets"] == "public": u_sets = UserSets.get(db_conn, user_id=user["id"]) data["sets"] = [set_.deliver() for set_ in u_sets.list_sets(db_conn)] if "follows" in request["params"] and user["settings"]["view_follows"] == "public": data["follows"] = [follow.deliver() for follow in Follow.list(db_conn, user_id=user["id"])] if "avatar" in request["params"]: size = int(request["params"]["avatar"]) data["avatar"] = get_avatar(user["email"], size if size else None) return 200, data
def create_password_route(request, user_id): """ Update a user's password if the token is valid. """ db_conn = request['db_conn'] user = get_user(db_conn, {'id': user_id}) if not user: return abort(404, 'FstipA94SDa0qZ3IwRtcMQ') token = request['params'].get('token') valid = is_valid_token(user, token) if not valid: return abort(403, 'qe27rSkpQbi49-pbqEl7Kw') given_password = request['params'].get('password') update_user_password(db_conn, user, {'password': given_password}) return _log_in(user)
def create_password_route(request, user_id): """ Update a user's password if the token is valid. """ db_conn = request["db_conn"] user = get_user({"id": user_id}, db_conn) if not user: return abort(404) token = request["params"].get("token") valid = is_valid_token(user, token) if not valid: return abort(403) given_password = request["params"].get("password") update_user_password(user, {"password": given_password}, db_conn) return _log_in(user)
def update_user_route(request, user_id): """ Update the user. Must be the current user. """ db_conn = request["db_conn"] user = get_user({"id": user_id}, db_conn) current_user = get_current_user(request) if not user: return abort(404) if not user["id"] == current_user["id"]: return abort(401) user, errors = update_user(user, request["params"], db_conn) if len(errors): return 400, {"errors": errors, "ref": "AS7LCAWiOOyeEbNOrbsegVY9"} return 200, {"user": deliver_user(user, access="private")}
def get_recommended_sets(request): db_conn = request['db_conn'] sets = Set.get_all(db_conn) if not sets: return abort(404) return 200, { 'sets': [set_.deliver() for set_ in sets] }
def get_recommended_subjects_route(request): db_conn = request['db_conn'] subjects = get_recommended_subjects(db_conn) if not subjects: return abort(404, '44bN2oD3TuOWc8wrgRmeeA') return 200, { 'subjects': [deliver_subject(subject) for subject in subjects] }
def follow_route(request): """ Follow a card, unit, or set. """ # TODO-3 simplify this method. does some of this belong in the model? current_user = get_current_user(request) if not current_user: return abort(401) follow_data = dict(**request['params']) follow_data['user_id'] = current_user['id'] follow = Follow(follow_data) errors = follow.validate() if errors: return 400, { 'errors': errors, 'ref': '4Qn9oWVWiGKvXSONQKHSy1T6' } # Ensure the entity exists TODO-3 should this be a model validation? if follow['entity']['kind'] == 'topic': entity = Topic.get(id=follow['entity']['id']) else: entity = get_latest_accepted(follow['entity']['kind'], follow['entity']['id']) if not entity: return abort(404) # Ensure we don't already follow TODO-3 should this be a model validation? prev = Follow.list(user_id=current_user['id'], entity_id=follow_data['entity']['id']) if prev: return abort(409) follow, errors = follow.save() if errors: return 400, { 'errors': errors, 'ref': 'gKU6wgTItxpKyDs0eAlonCmi', } return 200, {'follow': follow.deliver(access='private')}
def get_current_user_route(request): """ Get current user's information. """ current_user = get_current_user(request) if not current_user: return abort(401) return 200, {'user': current_user.deliver(access='private')}
def update_user_route(request, user_id): """ Update the user. Must be the current user. """ user = User.get(id=user_id) current_user = get_current_user(request) if not user: return abort(404) if not user['id'] == current_user['id']: return abort(401) user, errors = user.update(request['params']) if len(errors): return 400, { 'errors': errors, 'ref': 'AS7LCAWiOOyeEbNOrbsegVY9', } return 200, {'user': user.deliver(access='private')}
def get_current_user_route(request): """ Get current user's information. """ current_user = get_current_user(request) if not current_user: return abort(401, 'l9BCKn1zQ5KRgFRYujqU7g') return 200, {'user': deliver_user(current_user, access='private')}
def get_current_user_route(request): """ Get current user's information. """ current_user = get_current_user(request) if not current_user: return abort(401) return 200, {"user": deliver_user(current_user, access="private")}
def get_recommended_subjects(request): db_conn = request['db_conn'] entity_ids = ('JAFGYFWhILcsiByyH2O9frcU', ) if config['debug']: entity_ids = ('subjectAll', ) subjects = Subject.list_by_entity_ids(db_conn, entity_ids) if not subjects: return abort(404) return 200, {'subjects': [subject.deliver() for subject in subjects]}
def test_abort(): """ Expect to return a standard fail status. """ code, response = abort(404) assert code == 404 assert 'errors' in response assert response['errors'][0]['message'] == '404 Not Found'
def add_set_route(request, user_id, set_id): """ Add a set to the learner's list of sets. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) if user_id != current_user['id']: return abort(403) set_ = Set.get(db_conn, entity_id=set_id) if not set_: return abort(404) uset = UserSets.get(db_conn, user_id=user_id) if uset and set_id in uset['set_ids']: return 400, { 'errors': [{ 'name': 'set_id', 'message': 'Set is already added.', }], 'ref': 'kPZ95zM3oxFDGGl8vBdR3J3o', } if uset: uset['set_ids'].append(set_id) uset, errors = uset.save(db_conn) else: uset, errors = UserSets.insert(db_conn, { 'user_id': user_id, 'set_ids': [set_id], }) if errors: return 400, { 'errors': errors, 'ref': 'zCFUbLBTg9n2DnTkQYbqO4X9' } return 200, {'sets': uset['set_ids']}
def _log_in(user): """ Log in a given user, and return an appropriate response. Used by sign up, log in, and reset password. """ session_id = log_in_user(user) if session_id: return 200, {"user": deliver_user(user, access="private"), "cookies": {"session_id": session_id}} return abort(401)
def create_token_route(request): """ Create an email token for the user. """ user = User.get(email=request['params'].get('email')) if not user: return abort(404) user.get_email_token() return 200, {}
def create_token_route(request): """ Create an email token for the user. """ db_conn = request["db_conn"] user = get_user({"email": request["params"].get("email")}, db_conn) if not user: return abort(404) get_email_token(user) return 200, {}
def call_handler(request): """ Given a request dictionary, call the appropriate handler. Return a tuple of code (str), data (dict), and cookies (list). """ method = request['method'] if method not in ('GET', 'POST', 'PUT', 'DELETE'): return abort(405) path = request['path'] handler, parameters = find_path(method, path) if not handler: return abort(404) try: return handler(request=request, **parameters) except Exception: if config['debug']: return 500, format_exc() return abort(500)
def list_notices_route(request): """ List notices for current user. Take parameters `limit`, `skip`, `tag`, and `read`. """ current_user = get_current_user(request) if not current_user: return abort(401) notices = Notice.list(user_id=current_user['id'], **request['params']) output = {'notices': [notice.deliver(access='private') for notice in notices]} return 200, output
def call_handler(environ): """ Given a WSGI environment, call the appropriate handler. Return a tuple of code (str), data (dict), and cookies (list). """ method = environ['REQUEST_METHOD'] if method not in ('GET', 'POST', 'PUT', 'DELETE'): return abort(405) path = environ['SCRIPT_NAME'] + environ['PATH_INFO'] handler, parameters = find_path(method, path) if not handler: return abort(404) try: return handler(request=construct_request(environ), **parameters) except Exception: if config['debug']: return 500, format_exc() return abort(500)
def unfollow_route(request, follow_id): """ Remove a follow. Must be current user's own follow. """ db_conn = request["db_conn"] current_user = get_current_user(request) if not current_user: return abort(401) follow = Follow.get(db_conn, id=follow_id) if not follow: return abort(404) if follow["user_id"] != current_user["id"]: return abort(403) follow, errors = follow.delete(db_conn) if errors: return 400, {"errors": errors, "ref": "iGmpx8UwoFcKNmSKq9Aocy1a"} return 200, {}