def save(self, db_conn): """ Overwrite save method to add to Elasticsearch. """ # TODO-2 should we validate the save worked before going to ES? from database.topic import get_topic, deliver_topic from database.user import get_user, deliver_user data = json_prep(self.deliver()) topic = get_topic({'id': self['topic_id']}, db_conn) if topic: data['topic'] = json_prep(deliver_topic(topic)) user = get_user({'id': self['user_id']}, db_conn) if user: data['user'] = json_prep(deliver_user(user)) es.index( index='entity', doc_type='post', body=data, id=self['id'], ) return super().save(db_conn)
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_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 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 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 test_deliver_topic(db_conn): create_test_topics(db_conn) params = { 'id': test_topic_id, } topic = get_topic(db_conn, params) topic = deliver_topic(topic, access=None) assert topic
def list_topics_route(request): """ List topics by specified parameters. """ db_conn = request['db_conn'] entity_id = request['params'].get('entity_id') if entity_id: topics = list_topics_by_entity_id(db_conn, entity_id, {}) return 200, {'topics': [deliver_topic(topic) for topic in topics]} return abort(404, '4ubANCBYSvCABWyqvjH62A')
def create_topic_route(request): """ Create a new topic. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401, 'WJ50hh2STw-5ujy62wyXew') # ## STEP 1) Create topic topic_data = request['params'] if not topic_data: return 400, { 'errors': [{ 'name': 'topic', 'message': 'Missing topic data.', 'ref': 'PmocSz4OQUGa2T7x98yVlg', }], } topic_data['user_id'] = current_user['id'] topic, errors = insert_topic(db_conn, topic_data) if errors: return 400, {'errors': errors, 'ref': 'UoyXf_vwSWee0tCWgxg4Zw'} # ## STEP 2) Add author as a follower insert_follow( db_conn, { 'user_id': current_user['id'], 'entity_id': topic['id'], 'entity_kind': 'topic', }) # TODO-2 also follow the entity automatically IF needed # ## STEP 3) Send out any needed notices send_notices(db_conn, entity_id=topic['entity_id'], entity_kind=topic['entity_kind'], notice_kind='create_topic', notice_data={ 'user_name': current_user['name'], 'topic_name': topic['name'], 'entity_kind': topic['entity_kind'], 'entity_name': convert_uuid_to_slug(topic['entity_id']), }) # ## STEP 4) Return response return 200, { 'topic': deliver_topic(topic), }
def get_topic_route(request, topic_id): """ Get a topic """ db_conn = request['db_conn'] topic = get_topic(db_conn, {'id': topic_id}) if not topic: return 404, { 'errors': [{ 'name': 'topic_id', 'message': c('no_topic'), }], 'ref': 'o5V4uBFXQC6WNeyKrhn5kA', } return 200, {'topic': deliver_topic(topic)}
def get_set_route(request, set_id): """ Get a specific set given an ID. """ db_conn = request['db_conn'] set_ = Set.get_latest_accepted(db_conn, set_id) if not set_: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = list_topics_by_entity_id(set_id, {}, db_conn) versions = Set.get_versions(db_conn, entity_id=set_id) units = set_.list_units(db_conn) return 200, { 'set': set_.deliver(), # 'set_parameters': set_.fetch_parameters(), 'topics': [deliver_topic(topic) for topic in topics], 'versions': [version.deliver() for version in versions], 'units': [unit.deliver() for unit in units], }
def add_post_to_es(db_conn, post): """ Upsert the post data into elasticsearch. """ from database.topic import get_topic, deliver_topic from database.user import get_user, deliver_user data = json_prep(deliver_post(post)) topic = get_topic(db_conn, {'id': post['topic_id']}) if topic: data['topic'] = json_prep(deliver_topic(topic)) user = get_user(db_conn, {'id': post['user_id']}) if user: data['user'] = json_prep(deliver_user(user)) return es.index( index='entity', doc_type='post', body=data, id=convert_uuid_to_slug(post['id']), )
def create_topic_route(request): """ Create a new topic. The first post (or proposal) must be provided. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) # ## STEP 1) Create post and topic (and entity) instances topic_data = request['params'].get('topic') post_data = request['params'].get('post') if not topic_data: return 400, { 'errors': [{ 'name': 'topic', 'message': 'Missing topic data.' }], 'ref': 'zknSd46f2hRNjSjVHCg6YLwN' } if not post_data: return 400, { 'errors': [{ 'name': 'post', 'message': 'Missing post data.' }], 'ref': 'Qki4oWX4nTdNAjYI8z5iNawr' } topic_data = omit(topic_data, ('id', 'created', 'modified')) topic_data['user_id'] = current_user['id'] topic_data, topic_errors = validate_topic(topic_data, db_conn) post_data = omit(post_data, ( 'id', 'created', 'modified', )) post_data['user_id'] = current_user['id'] post_data['topic_id'] = topic_data['id'] post_ = instance_post_facade(post_data) post_kind = post_['kind'] if post_kind == 'proposal': entity = instance_new_entity(request['params']) entity_kind = get_kind(request['params']) post_['entity_version'] = { 'id': entity['id'], 'kind': entity_kind, } # ## STEP 2) Validate post and topic (and entity) instances errors = prefix_error_names('topic.', topic_errors) errors = errors + prefix_error_names('post.', post_.validate(db_conn)) if post_kind == 'proposal': errors = (errors + prefix_error_names('entity.', entity.validate(db_conn))) if len(errors): return 400, {'errors': errors, 'ref': 'TAY5pX3ghWBkSIVGTHzpQySa'} # ## STEP 3) Save post and topic (and entity) topic_data, topic_errors = insert_topic(topic_data, db_conn) post_['topic_id'] = topic_data['id'] post_.save(db_conn) if post_kind == 'proposal': entity.save(db_conn) # ## STEP 4) Add author as a follower insert_follow( { 'user_id': current_user['id'], 'entity': { 'id': topic_data['id'], 'kind': 'topic', } }, db_conn) # TODO-2 also follow the entity automatically IF needed # ## STEP 5) Send out any needed notices send_notices(db_conn, entity_id=topic_data['entity']['id'], entity_kind=topic_data['entity']['kind'], notice_kind='create_topic', notice_data={ 'user_name': current_user['name'], 'topic_name': topic_data['name'], 'entity_kind': topic_data['entity']['kind'], 'entity_name': topic_data['entity']['id'], }) if post_kind == 'proposal': send_notices(db_conn, entity_id=topic_data['entity']['id'], entity_kind=topic_data['entity']['kind'], notice_kind='create_proposal', notice_data={ 'user_name': current_user['name'], 'topic_name': topic_data['name'], 'entity_kind': topic_data['entity']['kind'], 'entity_name': topic_data['entity']['id'], }) # ## STEP 5) Return response return 200, {'topic': deliver_topic(topic_data), 'post': post_.deliver()}
def get_posts_route(request, topic_id): """ Get a reverse chronological listing of posts for given topic. Includes topic meta data and posts (or proposals or votes). Paginates. """ db_conn = request['db_conn'] # Is the topic valid? topic = get_topic({'id': topic_id}, db_conn) if not topic: return 404, { 'errors': [{ 'name': 'topic_id', 'message': c('no_topic'), }], 'ref': 'pgnNbqSP1VUWkOYq8MVGPrSS', } # Pull the entity entity_kind = topic['entity']['kind'] entity = get_latest_accepted(db_conn, entity_kind, topic['entity']['id']) # Pull all kinds of posts posts = get_posts_facade(db_conn, limit=request['params'].get('limit') or 10, skip=request['params'].get('skip') or 0, topic_id=topic_id) # For proposals, pull up the proposal entity version # ...then pull up the previous version # ...make a diff between the previous and the proposal entity version diffs = {} entity_versions = {} for post_ in posts: if post_['kind'] == 'proposal': entity_version = entity_versions[post_['id']] = get_version( db_conn, post_['entity_version']['kind'], post_['entity_version']['id']) previous_version = get_version(db_conn, post_['entity_version']['kind'], entity_version['previous_id']) if previous_version: diffs[post_['id']] = object_diff(previous_version.deliver(), entity_version.deliver()) # TODO-2 SPLITUP create new endpoint for this instead users = {} for post_ in posts: user_id = post_['user_id'] if user_id not in users: user = get_user({'id': user_id}, db_conn) if user: users[user_id] = { 'name': user['name'], 'avatar': get_avatar(user['email'], 48), } # TODO-2 SPLITUP create new endpoints for these instead output = { 'topic': deliver_topic(topic), 'posts': [p.deliver() for p in posts], 'entity_versions': {p: ev.deliver('view') for p, ev in entity_versions.items()}, # 'diffs': diffs, TODO-2 this causes a circular dependency 'users': users, } if entity: output[entity_kind] = entity.deliver() return 200, output