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 # Subjects 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'] = [deliver_post(post) for post in list_posts({'user_id': user['id']}, db_conn)] if ('subjects' in request['params'] and user['settings']['view_subjects'] == 'public'): data['subjects'] = [ subject.deliver() for subject in list_user_subjects_entity( user['id'], {}, db_conn)] if ('follows' in request['params'] and user['settings']['view_follows'] == 'public'): data['follows'] = [deliver_follow(follow) for follow in list_follows({'user_id': user['id']}, db_conn)] 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_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_kind = post_data['kind'] if post_kind == 'proposal': entities = instance_entities(request['params']) post_data['entity_versions'] = [] for entity in entities: entity_kind = get_kind(entity) post_data['entity_versions'].append({ 'id': entity['id'], 'kind': entity_kind, }) # ## STEP 2) Validate post and topic (and entity) instances errors = prefix_error_names('topic.', topic_errors) _, post_errors = validate_post(post_data, db_conn) errors = errors + prefix_error_names('post.', post_errors) if post_kind == 'proposal': for entity in entities: 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_data['topic_id'] = topic_data['id'] post_, errors = insert_post(post_data, db_conn) if post_kind == 'proposal': for entity in entities: 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': deliver_post(post_), }
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({'id': post_id}, db_conn) 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_.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 = update_post(post_, post_data, db_conn) 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_statuses(db_conn, post_) if post_kind == 'vote': proposal = get_post({'id': post_['replies_to_id']}, db_conn) update_entity_statuses(db_conn, proposal) # ## STEP 5) Return response ## # return 200, {'post': deliver_post(post_)}
def create_post_route(request, topic_id): """ Create a new post on a given topic. Proposal: must include entity (card, unit, or subject) information. Vote: must refer to a valid proposal. """ db_conn = request['db_conn'] current_user = get_current_user(request) if not current_user: return abort(401) topic = get_topic({'id': topic_id}, db_conn) if not topic: return 404, { 'errors': [{ 'name': 'topic_id', 'message': c('no_topic'), }], 'ref': 'PCSFCxsJtnlP0x9WzbPoKcwM', } # ## STEP 1) Create post (and entity) instances post_data = request['params'].get('post') if not post_data: return 400, { 'errors': [{ 'name': 'post', 'message': 'Missing post data.', }], 'ref': 'ykQpZwJKq54MTCxgkx0p6baW' } post_data = omit(post_data, ( 'id', 'created', 'modified', )) post_data['user_id'] = current_user['id'] post_data['topic_id'] = topic_id post_kind = post_data['kind'] if post_kind == 'proposal': entities = instance_entities(request['params']) post_data['entity_versions'] = [] for entity in entities: entity_kind = get_kind(entity) post_data['entity_versions'].push({ 'id': entity['id'], 'kind': entity_kind, }) # ## STEP 2) Validate post (and entity) instances _, post_errors = validate_post(post_data, db_conn) errors = prefix_error_names('post.', post_errors) if post_kind == 'proposal': for entity in entities: errors = (errors + prefix_error_names('entity.', entity.validate(db_conn))) if len(errors): return 400, {'errors': errors, 'ref': 'tux33ztgFj9ittSpS7WKIkq7'} # ## STEP 3) Save post (and entity) post_, post_errors = insert_post(post_data, db_conn) if post_kind == 'proposal': for entity in entities: entity.save(db_conn) # ## STEP 4) Add author as a follower insert_follow( { 'user_id': current_user['id'], 'entity': { 'id': topic['id'], 'kind': 'topic', } }, db_conn) # TODO-2 also follow the entity # ## STEP 5) Make updates based on proposal / vote status if post_kind == 'proposal': update_entity_statuses(db_conn, post_) if post_kind == 'vote': proposal = get_post({'id': post_data['replies_to_id']}, db_conn) update_entity_statuses(db_conn, proposal) # ## STEP 6) Send notices if post_kind == 'proposal': send_notices(db_conn, entity_id=topic['entity']['id'], entity_kind=topic['entity']['kind'], notice_kind='create_proposal', notice_data={ 'user_name': current_user['name'], 'topic_name': topic['name'], 'entity_kind': topic['entity']['kind'], 'entity_name': topic['entity']['id'], }) # ## STEP 7) Return response return 200, {'post': deliver_post(post_data)}
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 = list_posts( { 'limit': request['params'].get('limit') or 10, 'skip': request['params'].get('skip') or 0, 'topic_id': topic_id, }, db_conn) # 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_versions[post_['id']] = [ get_version(db_conn, p_entity_version['kind'], p_entity_version['id']) for p_entity_version in post_['entity_versions'] ] # TODO-2 re-enable diffs # previous_version = get_version( # db_conn, # p_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': [deliver_post(p) for p in posts], 'entity_versions': { p: [ev.deliver('view') for ev in evs] for p, evs 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
def test_deliver_post(db_conn): create_test_posts(db_conn) data = get_post(db_conn, { 'id': post_uuid, }) assert deliver_post(data, access=None)