示例#1
0
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')}
示例#2
0
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']}
示例#3
0
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)}
示例#4
0
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")}
示例#5
0
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
示例#6
0
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')}
示例#7
0
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'])),
        }
    }
示例#8
0
文件: next.py 项目: Folashade/sagefy
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']),
        }
    }
示例#9
0
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)}
示例#10
0
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_,
    }
示例#11
0
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, {}
示例#12
0
文件: card.py 项目: Folashade/sagefy
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_,
    }
示例#13
0
文件: topic.py 项目: Folashade/sagefy
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()}
示例#14
0
文件: notice.py 项目: wincax88/sagefy
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')}
示例#15
0
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_,
    }
示例#16
0
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_,
    }
示例#17
0
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]
    }
示例#18
0
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']}
示例#19
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_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()}
示例#20
0
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']}
示例#21
0
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
示例#22
0
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')}
示例#23
0
文件: user.py 项目: Folashade/sagefy
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')}
示例#24
0
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_}
示例#25
0
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')}
示例#26
0
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")}
示例#27
0
def test_get_current_user(users_table, db_conn):
    """
    Expect to get the current user given session info.
    """

    create_user_in_db(users_table, db_conn)
    token = log_in()
    user = get_current_user({'cookies': {'session_id': token}})
    assert user
    assert user['id'] == 'abcd1234'
示例#28
0
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_}
示例#29
0
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_}
示例#30
0
def get_my_recently_created_units_route(request):
    """
  Get the units the user most recently created.
  """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401, '2fReKMNNQg6BhnmfBI3UiQ')
    db_conn = request['db_conn']
    units = list_my_recently_created_units(db_conn, current_user['id'])
    return 200, {
        'units': [deliver_unit(unit) for unit in units],
    }
示例#31
0
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
示例#32
0
def get_my_recently_created_subjects_route(request):
    """
    Get the subjects the user most recently created.
    """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)
    db_conn = request['db_conn']
    subjects = get_my_recently_created_subjects(current_user, db_conn)
    return 200, {
        'subjects': [subject.deliver() for subject in subjects],
    }
示例#33
0
def get_my_recently_created_subjects_route(request):
    """
  Get the subjects the user most recently created.
  """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401, 'MEnwdloNQLWEVnZNT1YRFg')
    db_conn = request['db_conn']
    subjects = list_my_recently_created_subjects(db_conn, current_user['id'])
    return 200, {
        'subjects': [deliver_subject(subject) for subject in subjects],
    }
示例#34
0
def get_my_recently_created_units_route(request):
    """
    Get the units the user most recently created.
    """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)
    db_conn = request['db_conn']
    units = get_my_recently_created_units(current_user, db_conn)
    return 200, {
        'units': [unit.deliver() for unit in units],
    }
示例#35
0
def select_subject_route(request, user_id, subject_id):
  """
  Select the subject to work on.

  NEXT STATE
  POST Choose Subject   (Update Learner Context)
    -> GET Choose Subject ...when subject is complete
    -> GET Choose Unit  ...when in learn or review mode
    -> GET Learn Card   ...when in diagnosis
      (Unit auto chosen)
  """

  db_conn = request['db_conn']
  current_user = get_current_user(request)
  if not current_user:
    return abort(401, 'f8IynoM9RLmW0Ae14_Hukw')
  subject = get_latest_accepted_subject(db_conn, subject_id)
  set_learning_context(current_user, subject=subject)
  buckets = traverse(db_conn, current_user, subject)
  # When in diagnosis, choose the unit and card automagically.
  # if buckets.get('diagnose'):
  #   unit = buckets['diagnose'][0]
  #   card = choose_card(db_conn, current_user, unit)
  #   next_ = {
  #     'method': 'GET',
  #     'path': '/s/cards/{card_id}/learn'
  #         .format(card_id=convert_uuid_to_slug(card['entity_id'])),
  #   }
  #   set_learning_context(
  #     current_user,
  #     next=next_, unit=unit, card=card)
  # When in learn or review mode, lead me to choose a unit.
  # elif buckets.get('review') or
  if buckets.get('learn'):
    next_ = {
      'method': 'GET',
      'path': '/s/subjects/{subject_id}/units'.format(
        subject_id=convert_uuid_to_slug(subject_id)
      ),
    }
    set_learning_context(current_user, next=next_)
  # If the subject is complete, lead the learner to choose another subject.
  else:
    next_ = {
      'method': 'GET',
      'path': '/s/users/{user_id}/subjects'.format(
        user_id=convert_uuid_to_slug(current_user['id'])
      ),
    }
    set_learning_context(current_user, next=next_, unit=None, subject=None)
  return 200, {'next': next_}
示例#36
0
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
示例#37
0
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),
    }
示例#38
0
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'
示例#39
0
def list_notices_route(request):
  """
  List notices for current user.
  Take parameters `limit`, `skip`, `tag`, and `read`.
  """

  db_conn = request['db_conn']
  current_user = get_current_user(request)
  if not current_user:
    return abort(401, '9oMIw3V8S3WeaLf9IgbmaQ')
  params = extend({}, request['params'], {'user_id': current_user['id']})
  notices = list_notices(db_conn, params)
  output = {'notices': [deliver_notice(notice, access='private')
                        for notice in notices]}
  return 200, output
示例#40
0
def test_get_current_user(db_conn):
    """
  Expect to get the current user given session info.
  """

    create_user_in_db(db_conn)
    token = log_in()
    user = get_current_user({
        'cookies': {
            'session_id': token
        },
        'db_conn': db_conn,
    })
    assert user
    assert user['id'] == convert_slug_to_uuid(user_id)
示例#41
0
def list_notices_route(request):
    """
    List notices for current user.
    Take parameters `limit`, `skip`, `tag`, and `read`.
    """

    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401)
    params = extend({}, request['params'], {'user_id': current_user['id']})
    notices = list_notices(params, db_conn)
    output = {'notices': [deliver_notice(notice, access='private')
                          for notice in notices]}
    return 200, output
示例#42
0
def follow_route(request):
    """
  Follow a card, unit, or subject.
  """

    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401, '0kW_gcpzQ7GomlCM28R8hw')
    follow_data = dict(**request['params'])
    follow_data['user_id'] = current_user['id']
    follow, errors = insert_follow(db_conn, follow_data)
    if errors:
        return 400, {'errors': errors, 'ref': 'R4AAxO7PT7udr2huRHIbnA'}
    return 200, {'follow': deliver_follow(follow, access='private')}
示例#43
0
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")}
示例#44
0
def get_user_route(request, user_id):
  """
  Get the user by their ID.
  """

  db_conn = request['db_conn']
  user = get_user(db_conn, {'id': user_id})
  if not user:
    return abort(404, 'Tp5JnWO1SWms2lTdhw3bJQ')
  current_user = get_current_user(request)
  access = 'private' if (current_user and
                         user['id'] == current_user['id']) else None
  data = {'user': deliver_user(user, access)}
  if 'avatar' in request['params']:
    size = int(request['params']['avatar']) or None
    data['avatar'] = get_avatar(user['email'], size)
  return 200, data
示例#45
0
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')}
示例#46
0
def follow_route(request):
    """
    Follow a card, unit, or set.
    """

    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, errors = insert_follow(follow_data, db_conn)
    if errors:
        return 400, {'errors': errors, 'ref': '4Qn9oWVWiGKvXSONQKHSy1T6'}

    return 200, {'follow': deliver_follow(follow, access='private')}
示例#47
0
文件: user.py 项目: Folashade/sagefy
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')}
示例#48
0
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']}
示例#49
0
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)

    follows = Follow.list(db_conn, user_id=current_user["id"], **request["params"])

    output = {"follows": [follow.deliver(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
示例#50
0
def get_set_units_route(request, set_id):
    """
    Present a small number of units the learner can choose from.

    NEXT STATE
    GET Choose Unit
        -> POST Choose Unit
    """

    db_conn = request['db_conn']

    # TODO-3 simplify this method. should it be part of the models?

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    context = get_learning_context(current_user)
    next_ = {
        'method': 'POST',
        'path': '/s/sets/{set_id}/units/{unit_id}'
                  .format(set_id=context.get('set', {}).get('entity_id'),
                          unit_id='{unit_id}'),
    }
    set_learning_context(current_user, next=next_)

    set_ = Set.get_latest_accepted(db_conn, set_id)

    # Pull a list of up to 5 units to choose from based on priority.
    buckets = traverse(db_conn, current_user, set_)
    units = buckets['learn'][:5]
    # TODO-3 Time estimates per unit for mastery.

    return 200, {
        'next': next_,
        'units': [unit.deliver() for unit in units],
        # For the menu, it must return the name and ID of the set
        'set': set_.deliver(),
        'current_unit_id': context.get('unit', {}).get('entity_id'),
    }
示例#51
0
def select_set_route(request, user_id, set_id):
    """
    Select the set to work on.

    NEXT STATE
    POST Choose Set   (Update Learner Context)
        -> GET View Set Tree
    """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    set_ = Set.get_latest_accepted(set_id)
    next_ = {
        'method': 'GET',
        'path': '/s/sets/{set_id}/tree'
                .format(set_id=set_id),
    }
    current_user.set_learning_context(set=set_.data, next=next_)

    return 200, {'next': next_}
示例#52
0
def get_follows_route(request):
    """
    Get a list of the users follows.
    """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    follows = Follow.list(user_id=current_user['id'], **request['params'])

    output = {
        'follows': [follow.deliver(access='private') for follow in follows]
    }

    # TODO-3 SPLITUP should this be a different endpoint?
    if 'entities' in request['params']:
        entities = flush_entities(follow['entity'] for follow in follows)
        output['entities'] = [entity.deliver() if entity else None
                              for entity in entities]

    return 200, output
示例#53
0
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, {}
示例#54
0
文件: user.py 项目: Folashade/sagefy
def get_user_route(request, user_id):
    """
    Get the user by their ID.
    """

    user = User.get(id=user_id)
    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'] = user.deliver(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(user_id=user['id'])]
    if ('sets' in request['params']
            and user['settings']['view_sets'] == 'public'):
        u_sets = UserSets.get(user_id=user['id'])
        data['sets'] = [set_.deliver() for set_ in u_sets.list_sets()]
    if ('follows' in request['params']
            and user['settings']['view_follows'] == 'public'):
        data['follows'] = [follow.deliver() for follow in
                           Follow.list(user_id=user['id'])]
    if 'avatar' in request['params']:
        size = int(request['params']['avatar'])
        data['avatar'] = user.get_avatar(size if size else None)

    return 200, data
示例#55
0
def unfollow_route(request, follow_id):
    """
    Remove a follow. Must be current user's own follow.
    """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    follow = Follow.get(id=follow_id)
    if not follow:
        return abort(404)

    if follow['user_id'] != current_user['id']:
        return abort(403)

    follow, errors = follow.delete()
    if errors:
        return 400, {
            'errors': errors,
            'ref': 'iGmpx8UwoFcKNmSKq9Aocy1a'
        }

    return 200, {}
示例#56
0
def get_set_tree_route(request, set_id):
    """
    Render the tree of units that exists within a set.

    Contexts:
    - Search set, preview units in set
    - Pre diagnosis
    - Learner view progress in set
    - Set complete

    NEXT STATE
    GET View Set Tree
        -> GET Choose Set    ...when set is complete
        -> GET Choose Unit   ...when in learn or review mode
        -> GET Learn Card    ...when in diagnosis
            (Unit auto chosen)

    TODO-2 merge with get_set_units_route
    TODO-2 simplify this method
    """

    db_conn = request['db_conn']

    set_ = Set.get(db_conn, entity_id=set_id)

    if not set_:
        return abort(404)

    units = set_.list_units(db_conn)

    # For the menu, it must return the name and ID of the set
    output = {
        'set': set_.deliver(),
        'units': [u.deliver() for u in units],
    }

    current_user = get_current_user(request)

    if not current_user:
        return 200, output

    context = get_learning_context(current_user) if current_user else {}
    buckets = traverse(db_conn, current_user, set_)
    output['buckets'] = {
        'diagnose': [u['entity_id'] for u in buckets['diagnose']],
        'review': [u['entity_id'] for u in buckets['review']],
        'learn': [u['entity_id'] for u in buckets['learn']],
        'done': [u['entity_id'] for u in buckets['done']],
    }

    # If we are just previewing, don't update anything
    if set_id != context.get('set', {}).get('entity_id'):
        return 200, output

    # When in diagnosis, choose the unit and card automagically.
    if buckets['diagnose']:
        unit = buckets['diagnose'][0]
        card = choose_card(db_conn, current_user, unit)
        next_ = {
            'method': 'GET',
            'path': '/s/cards/{card_id}/learn'
                    .format(card_id=card['entity_id']),
        }
        set_learning_context(
            current_user,
            next=next_, unit=unit.data, card=card.data)

    # When in learn or review mode, lead me to choose a unit.
    elif buckets['review'] or buckets['learn']:
        next_ = {
            'method': 'GET',
            'path': '/s/sets/{set_id}/units'
                    .format(set_id=set_id),
        }
        set_learning_context(current_user, next=next_)

    # If the set is complete, lead the learner to choose another set.
    else:
        next_ = {
            'method': 'GET',
            'path': '/s/users/{user_id}/sets'
                    .format(user_id=current_user['id']),
        }
        set_learning_context(current_user, next=next_, unit=None, set=None)

    output['next'] = next_
    return 200, output
示例#57
0
文件: topic.py 项目: Folashade/sagefy
def create_post_route(request, topic_id):
    """
    Create a new post on a given topic.
    Proposal: must include entity (card, unit, or set) information.
    Vote: must refer to a valid proposal.
    """

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    topic = Topic.get(id=topic_id)
    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_ = 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 entity) instances
    errors = prefix_error_names('post.', post_.validate())
    if post_kind == 'proposal':
        errors = errors + prefix_error_names('entity.', entity.validate())
    if len(errors):
        return 400, {
            'errors': errors,
            'ref': 'tux33ztgFj9ittSpS7WKIkq7'
        }

    # ## STEP 3) Save post (and entity)
    post_.save()
    if post_kind == 'proposal':
        entity.save()

    # ## STEP 4) Add author as a follower
    Follow.insert({
        'user_id': current_user['id'],
        'entity': {
            'id': topic['id'],
            'kind': 'topic',
        }
    })
    # TODO-2 also follow the entity

    # ## STEP 5) Make updates based on proposal / vote status
    if post_kind == 'proposal':
        update_entity_status(post_)
    if post_kind == 'vote':
        proposal = Proposal.get(id=post_['replies_to_id'])
        update_entity_status(proposal)

    # ## STEP 6) Return response
    return 200, {'post': post_.deliver()}
示例#58
0
文件: card.py 项目: Folashade/sagefy
def respond_to_card_route(request, card_id):
    """
    Record and process a learner's response to a card.

    NEXT STATE
    POST Respond Card
        -> GET Learn Card      ...when not ready
        -> GET Choose Unit     ...when ready, but still units
        -> GET View Set Tree   ...when ready and done
    """

    # TODO-3 simplify this method.
    #      perhaps smaller methods or move to model layer?

    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 card is the current one
    context = current_user.get_learning_context()
    if context.get('card', {}).get('entity_id') != card['entity_id']:
        return abort(400)

    r = seq_update(current_user, card, request['params'].get('response'))
    errors, response, feedback = (r.get('errors'), r.get('response'),
                                  r.get('feedback'))
    if errors:
        return 400, {
            'errors': errors,
            'ref': 'wtyOJPoy4bh76OIbYp8mS3LP',
        }

    set_ = Set(context.get('set'))
    unit = Unit(context.get('unit'))

    status = judge(unit, current_user)

    # If we are done with this current unit...
    if status == "done":
        buckets = traverse(current_user, set_)

        # If there are units to be diagnosed...
        if buckets['diagnose']:
            unit = buckets['diagnose'][0]
            next_card = choose_card(current_user, unit)
            next_ = {
                'method': 'GET',
                'path': '/s/cards/{card_id}/learn'
                        .format(card_id=next_card['entity_id']),
            }
            current_user.set_learning_context(
                card=next_card.data, unit=unit.data, next=next_)

        # If there are units to be learned or reviewed...
        elif buckets['learn'] or buckets['review']:
            next_ = {
                'method': 'GET',
                'path': '/s/sets/{set_id}/units'
                        .format(set_id=set_['entity_id']),
            }
            current_user.set_learning_context(card=None, unit=None, next=next_)

        # If we are out of units...
        else:
            next_ = {
                'method': 'GET',
                'path': '/s/sets/{set_id}/tree'
                        .format(set_id=set_['entity_id']),
            }
            current_user.set_learning_context(card=None, unit=None, next=next_)

    # If we are still reviewing, learning or diagnosing this unit...
    else:
        next_card = choose_card(current_user, unit)
        if next_card:
            next_ = {
                'method': 'GET',
                'path': '/s/cards/{card_id}/learn'
                        .format(card_id=next_card['entity_id']),
            }
            current_user.set_learning_context(card=next_card.data, next=next_)
        else:
            next_ = {}
            current_user.set_learning_context(next=next_)

    return 200, {
        'response': response.deliver(),
        'feedback': feedback,
        'next': next_,
    }
示例#59
0
文件: topic.py 项目: Folashade/sagefy
def create_topic_route(request):
    """
    Create a new topic.
    The first post (or proposal) must be provided.
    """

    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 = Topic(topic_data)
    post_data = omit(post_data, ('id', 'created', 'modified',))
    post_data['user_id'] = current_user['id']
    post_data['topic_id'] = topic['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.validate())
    errors = errors + prefix_error_names('post.', post_.validate())
    if post_kind == 'proposal':
        errors = errors + prefix_error_names('entity.', entity.validate())
    if len(errors):
        return 400, {
            'errors': errors,
            'ref': 'TAY5pX3ghWBkSIVGTHzpQySa'
        }

    # ## STEP 3) Save post and topic (and entity)
    topic.save()
    post_.save()
    if post_kind == 'proposal':
        entity.save()

    # ## STEP 4) Add author as a follower
    Follow.insert({
        'user_id': current_user['id'],
        'entity': {
            'id': topic['id'],
            'kind': 'topic',
        }
    })
    # TODO-2 also follow the entity automatically IF needed

    # ## STEP 5) Send out any needed notifications
    send_notices(
        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': topic['entity']['id'],
        }
    )

    # ## STEP 5) Return response
    return 200, {'topic': topic.deliver(), 'post': post_.deliver()}