Exemple #1
0
def test_invites_list_cache_clear(app, authed_client):
    """Sending an invite should clear the cache key for a user's list of invites."""
    app.config['REQUIRE_INVITE_CODE'] = True
    add_permissions(app, 'invites_send')
    Invite.from_inviter(1)  # Cache it

    authed_client.post(
        '/invites', data=json.dumps({'email': '*****@*****.**'})
    )
    sent_invites = Invite.from_inviter(1, include_dead=True)
    assert len(sent_invites) == 4
Exemple #2
0
def invites_view(user: User, used: bool, include_dead: bool) -> flask.Response:
    """
    View sent invites. If a user_id is specified, only invites sent by that user
    will be returned, otherwise only your invites are returned. If requester has
    the ``invites_view_others`` permission, they can view sent invites of another user.

    .. :quickref: Invite; View multiple invites.

    **Example response**:

    .. parsed-literal::

       {
         "status": "success",
         "response": [
            "<Invite>",
            "<Invite>"
         ]
       }

    :query boolean used: (Optional) Whether or not to only show used invites
        (overrides ``include_dead``)
    :query boolean include_dead: (Optional) Whether or not to include expired invites

    :>json list response: A list of invites

    :statuscode 200: View successful
    :statuscode 403: User does not have permission to view user's invites
    """
    invites = Invite.from_inviter(user.id,
                                  include_dead=include_dead,
                                  used=used)
    return flask.jsonify(invites)
Exemple #3
0
def ValInviteCode(code: Optional[str]) -> None:
    """
    Check an invite code against existing invite codes;
    Raises an APIException if the code isn't valid.

    :param code:          Invite code to check and verify

    :return:              An invite code or, if site is open registration, ``None``
    :raises APIException: The invite code cannot be used
    """
    if not app.config['REQUIRE_INVITE_CODE']:
        return

    if code is not None and (not isinstance(code, str) or len(code) != 24):
        raise APIException('Invite code must be a 24 character string.')

    invite = Invite.from_pk(code)
    if invite and not invite.invitee_id:
        time_since_usage = (datetime.utcnow().replace(tzinfo=pytz.utc) -
                            invite.time_sent)
        if time_since_usage.total_seconds() < app.config['INVITE_LIFETIME']:
            return

    if code:
        raise APIException(f'{code} is not a valid invite code.')
    raise APIException('An invite code is required for registration.')
Exemple #4
0
def test_revoke_invite(app, authed_client, code, expected, invites):
    """Revoking an invite should work only for active invites."""
    add_permissions(app, 'invites_revoke')
    response = authed_client.delete(f'/invites/{code}')
    user = User.from_pk(1)
    check_json_response(response, expected)
    assert user.invites == invites
    if 'expired' in expected and expected['expired'] is True:
        invite = Invite.from_pk(code, include_dead=True)
        assert invite.expired is True
Exemple #5
0
def invite_user(email: str):
    """
    Sends an invite to the provided email address. Requires the ``invites_send``
    permission. If the site is open registration, this endpoint will raise a
    400 Exception.

    .. :quickref: Invite; Send an invite.

    **Example request**:

    .. parsed-literal::

       POST /invites/an-invite-code HTTP/1.1

       {
         "email": "*****@*****.**"
       }

    **Example response**:

    .. parsed-literal::

       {
         "status": "success",
         "response": "<Invite>"
       }

    :<json string email: E-mail to send the invite to

    :statuscode 200: Successfully sent invite
    :statuscode 400: Unable to send invites or incorrect email
    :statuscode 403: Unauthorized to send invites
    """
    if not app.config['REQUIRE_INVITE_CODE']:
        raise APIException(
            'An invite code is not required to register, so invites have been disabled.'
        )
    if not flask.g.user.invites:
        raise APIException('You do not have an invite to send.')

    invite = Invite.new(inviter_id=flask.g.user.id,
                        email=email,
                        ip=flask.request.remote_addr)
    flask.g.user.invites -= 1
    db.session.commit()
    return flask.jsonify(invite)
Exemple #6
0
def view_invite(code: str) -> flask.Response:
    """
    View the details of an invite. Requires the ``invites_view`` permission.
    Requires the ``invites_view_others`` permission to view another user's invites.

    .. :quickref: Invite; View an active invite.

    **Example request**:

    .. parsed-literal::

       GET /invite HTTP/1.1

       {
         "code": "an-invite-code"
       }

    **Example response**:

    .. parsed-literal::

       HTTP/1.1 200 OK
       Vary: Accept
       Content-Type: application/json

       {
         "status": "success",
         "response": "<Invite>"
       }

    :statuscode 200: View successful
    :statuscode 404: Invite does not exist or user cannot view invite
    """
    return flask.jsonify(
        Invite.from_pk(
            code,
            include_dead=True,
            _404=True,
            asrt=InvitePermissions.VIEW_OTHERS,
        ))
Exemple #7
0
def revoke_invite(code: str) -> flask.Response:
    """
    Revokes an active invite code, preventing it from being used. The
    invite is returned to the user's account. Requires the
    ``invites_revoke`` permission to revoke one's own sent invite, and the
    ``invites_revoke_others`` permission to revoke another user's invites.

    .. :quickref: Invite; Revoke an active invite.

    **Example request**:

    .. parsed-literal::

       DELETE /invite HTTP/1.1

       {
         "id": "an-invite-code"
       }

    **Example response**:

    .. parsed-literal::

       {
         "status": "success",
         "response": "<Invite>"
       }

    :statuscode 200: Revocation successful
    :statuscode 403: Unauthorized to revoke invites
    :statuscode 404: Invite does not exist or user cannot view invite
    """
    invite = Invite.from_pk(code,
                            _404=True,
                            asrt=InvitePermissions.REVOKE_OTHERS)
    invite.expired = True
    invite.inviter.invites += 1
    db.session.commit()
    return flask.jsonify(invite)