예제 #1
0
파일: user.py 프로젝트: stevegt/sagefy
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
예제 #2
0
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_),
    }
예제 #3
0
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_)}
예제 #4
0
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)}
예제 #5
0
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)