コード例 #1
0
ファイル: players.py プロジェクト: onecrayon/api.ashes.live
def create_player(
        token: UUID4,
        data: schema.UserRegistrationIn,
        session: db.Session = Depends(get_session),
        _=Depends(anonymous_required),
):
    """Create a new player using the token obtained by requesting an invite.

    Will fail if requested by an authenticated user.
    """
    invite = session.query(Invite).filter(Invite.uuid == token).first()
    if invite is None:
        raise NotFoundException(
            detail="Token not found. Please request a new invite.")
    user = create_user(
        session,
        invite.email,
        data.password,
        username=data.username,
        description=data.description,
        newsletter_opt_in=data.newsletter_opt_in,
    )
    session.delete(invite)
    session.commit()
    access_token = access_token_for_user(user)
    return {"access_token": access_token, "token_type": "bearer", "user": user}
コード例 #2
0
def test_list_snapshots_bad_id(client: TestClient, session: db.Session, user1):
    """Not found error thrown when viewing non-existent deck"""
    deck = create_deck_for_user(session, user1)
    deleted_id = deck.id
    session.delete(deck)
    session.commit()
    response = client.get(f"/v2/decks/{deleted_id}/snapshots")
    assert response.status_code == status.HTTP_404_NOT_FOUND
コード例 #3
0
def test_delete_deck_bad_deck(client: TestClient, session: db.Session,
                              user_token):
    """Must disallow access to deck IDs that don't exist"""
    user, token = user_token
    deck = create_deck_for_user(session, user)
    bad_id = deck.id
    session.delete(deck)
    session.commit()
    response = client.delete(f"/v2/decks/{bad_id}",
                             headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == status.HTTP_403_FORBIDDEN
コード例 #4
0
def test_put_deck_bad_id(client: TestClient, session: db.Session, user_token):
    """Must not allow uploading a deck with a bad ID"""
    # Create a deck so that we can ensure no accidental ID collisions
    user, token = user_token
    deck = create_deck_for_user(session, user)
    bad_id = deck.id
    session.delete(deck)
    session.commit()
    valid_deck = _valid_deck_dict(session)
    valid_deck["id"] = bad_id
    response = client.put("/v2/decks",
                          json=valid_deck,
                          headers={"Authorization": f"Bearer {token}"})
    assert response.status_code == status.HTTP_403_FORBIDDEN
コード例 #5
0
def test_post_snapshot_bad_deck_id(client: TestClient, session: db.Session,
                                   user_token):
    """Must not allow creating a snapshot for a bad deck ID"""
    # Create a deck so that we can ensure no accidental ID collisions
    user, token = user_token
    deck = create_deck_for_user(session, user)
    bad_id = deck.id
    session.delete(deck)
    session.commit()
    response = client.post(
        f"/v2/decks/{bad_id}/snapshot",
        headers={"Authorization": f"Bearer {token}"},
    )
    assert response.status_code == status.HTTP_403_FORBIDDEN
コード例 #6
0
def test_get_deck_no_record(client: TestClient, session: db.Session, user1):
    """Trying to fetch an ID that no longer exists must fail correctly"""
    deck = create_deck_for_user(session, user1)
    deleted_id = deck.id
    session.delete(deck)
    session.commit()
    token = create_access_token(
        data={"sub": user1.badge},
        expires_delta=timedelta(minutes=15),
    )
    response = client.get(
        f"/v2/decks/{deleted_id}", headers={"Authorization": f"Bearer {token}"}
    )
    assert response.status_code == status.HTTP_404_NOT_FOUND
コード例 #7
0
def test_edit_snapshot_bad_id(client: TestClient, session: db.Session, user1, deck1):
    """Not found error thrown when viewing non-existent ID"""
    snapshot = create_snapshot_for_deck(session, user1, deck1)
    deleted_id = snapshot.id
    session.delete(snapshot)
    session.commit()
    token = create_access_token(
        data={"sub": user1.badge},
        expires_delta=timedelta(minutes=15),
    )
    response = client.patch(
        f"/v2/decks/snapshots/{deleted_id}",
        headers={"Authorization": f"Bearer {token}"},
        json={"title": "New title"},
    )
    assert response.status_code == status.HTTP_404_NOT_FOUND, response.json()
コード例 #8
0
def delete_deck(
    deck_id: int,
    session: db.Session = Depends(get_session),
    current_user: "******" = Depends(login_required),
):
    """Delete a deck.

    When requested for a source deck:

    * If there are no snapshots, the deck is truly deleted (unrecoverable). Intended use-case
      is for decks that get auto-saved, but not completed.
    * For decks with snapshots, it's a soft deletion that can potentially be recovered from (no
      user-facing support for recovering deleted decks currently planned, though). Deleted decks
      and their snapshots will be removed from all listings (including the stream).

    When requested for a snapshot, it's a soft deletion and the snapshot will no longer show up
    in any listings (including the stream).
    """
    deck: Deck = session.query(Deck).options(db.joinedload("source")).get(deck_id)
    if not deck or deck.user_id != current_user.id:
        raise NoUserAccessException(detail="You cannot delete a deck you do not own.")
    if deck.is_legacy:
        raise APIException(detail="You cannot delete legacy decks.")
    success_response = Response(status_code=status.HTTP_204_NO_CONTENT)
    # If the deck was previously deleted, just claim success and call it good
    if deck.is_deleted:
        return success_response
    # Check if we have any snapshots for source decks, and just delete that sucker for real if not
    if (
        not deck.is_snapshot
        and session.query(Deck).filter(Deck.source_id == deck.id).count() == 0
    ):
        session.query(DeckCard).filter(DeckCard.deck_id == deck.id).delete(
            synchronize_session=False
        )
        session.query(DeckDie).filter(DeckDie.deck_id == deck_id).delete(
            synchronize_session=False
        )
        session.query(DeckSelectedCard).filter(
            DeckSelectedCard.deck_id == deck_id
        ).delete(synchronize_session=False)
        session.query(Deck).filter(Deck.id == deck_id).delete(synchronize_session=False)
        session.commit()
        return success_response

    # Otherwise, we're looking at a snapshot or a source deck that has snapshots
    deck.is_deleted = True
    # For snapshots, we need to remove only the Stream entries for that snapshot (leave the rest
    #  of the source deck's snapshots alone).
    if deck.is_snapshot and deck.is_public:
        # Check to see if we have a Stream entry that needs updating
        stream_entry: Stream = (
            session.query(Stream)
            .filter(
                Stream.source_entity_id == deck.source.entity_id,
                Stream.entity_type == "deck",
                Stream.entity_id == deck.entity_id,
            )
            .first()
        )
        if stream_entry:
            # We have a stream entry pointed to this snapshot, so check if we have an older snapshot
            #  that we can swap in
            previous_snapshot: Deck = (
                session.query(Deck)
                .filter(
                    Deck.source_id == deck.source_id,
                    Deck.created < deck.created,
                    Deck.is_deleted.is_(False),
                )
                .order_by(Deck.created.desc())
                .first()
            )
            if previous_snapshot:
                stream_entry.entity_id = previous_snapshot.entity_id
                stream_entry.posted = previous_snapshot.created
            else:
                # Otherwise, just delete the stream entry because this deck no longer has any public
                #  snapshots
                session.delete(stream_entry)
    elif not deck.is_snapshot:
        # If we're not deleting a snapshot, then we need to completely clear out the Stream entry
        session.query(Stream).filter(
            Stream.source_entity_id == deck.entity_id, Stream.entity_type == "deck"
        ).delete(synchronize_session=False)
        # And mark all snapshots as deleted
        session.query(Deck).filter(
            Deck.source_id == deck.id,
            Deck.is_snapshot.is_(True),
            Deck.is_deleted.is_(False),
        ).update({"is_deleted": True}, synchronize_session=False)
    # Commit any pending changes, and return success
    session.commit()
    return success_response