def refresh_stream_for_entity(session: db.Session, entity_id: int, entity_type: str, source_entity_id: int): """Creates or updates the Stream entry for the given entity **Please note:** this method does not commit the changes! You must flush the session in the invoking method. """ if entity_type == "deck": entity = (session.query(Stream).filter( Stream.source_entity_id == source_entity_id, Stream.entity_type == "deck", ).first()) else: entity = session.query(Stream).filter( Stream.entity_id == entity_id).first() if not entity: entity = Stream( entity_id=entity_id, entity_type=entity_type, source_entity_id=source_entity_id, ) elif entity_type == "deck": # Decks are a special case; we update the Stream entity because the snapshots effectively # replace one another as far as most users are concerned entity.posted = datetime.utcnow() entity.entity_id = entity_id else: # Ignore comment edits return session.add(entity)
def test_banned_user(client: TestClient, session: db.Session): """Login requests by banned users throw an error""" user, password = utils.create_user_password(session) user.is_banned = True session.commit() response = client.post("/v2/token", {"username": user.email, "password": password}) assert response.status_code == status.HTTP_403_FORBIDDEN, response.json()
def test_request_password_reset_banned_user(client: TestClient, session: db.Session): """Banned users cannot request password resets""" user, _ = utils.create_user_token(session) user.is_banned = True session.commit() response = client.post("/v2/reset", json={"email": user.email}) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_create_card_populates_conjurations(client: TestClient, session: db.Session): """Creating a card adds its conjuration relationships""" # Verify that the pre-existing number of conjurations is what we expect assert session.query(CardConjuration).count() == 6 admin, token = create_admin_token(session) # Create the conjuration first conj_data = copy(MINIMUM_VALID_CARD) conj_data["card_type"] = "Conjuration" conj_data["copies"] = 1 conj_response = client.post("/v2/cards", json=conj_data, headers={"Authorization": f"Bearer {token}"}) assert conj_response.status_code == status.HTTP_201_CREATED, conj_response.json( ) # Then create the card that summons the conjuration card_data = copy(MINIMUM_VALID_CARD) card_data["name"] = "Summon Example Card" card_data[ "text"] = "Place an [[Example Card]] conjuration on your battlefield." card_response = client.post("/v2/cards", json=card_data, headers={"Authorization": f"Bearer {token}"}) assert card_response.status_code == status.HTTP_201_CREATED, card_response.json( ) # Then verify that the conjuration is linked to the card assert session.query(CardConjuration).count() == 7
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}
def test_get_banned_user(client: TestClient, session: db.Session): """Get user returns 404 for banned users""" user, _ = utils.create_user_token(session) user.is_banned = True session.commit() response = client.get(f"/v2/players/{user.badge}") assert response.status_code == status.HTTP_404_NOT_FOUND, response.json()
def check_notification_state(i): while 1: session = Session() ins_opition = queue_notification.get(True) print "Greenlets %s got : %s" % (i,time.asctime()), " " , ins_opition sql = """ SELECT result FROM cloud_result WHERE TIME = ( SELECT MAX( TIME ) FROM cloud_result ) AND uuid IN ( '%s' ) """ % ins_opition['uuid'] result = raw_sql(sql) # if result is empty, skip current loop. if not result: continue # analyst notification in another function ret = analyst_notification_result(result,ins_opition) print "Greenlets notification %s got : %s" % (i,time.asctime()) , ret if not ret: continue q = session.query(Instances).filter(Instances.uuid==ins_opition['uuid']) if q.all(): q.update( {Instances.notification_state:simplejson.dumps(ret)} ) session.commit()
def request_password_reset( data: UserEmailIn, session: db.Session = Depends(get_session), _=Depends(anonymous_required), ): """Request a reset password link for the given email.""" email = data.email.lower() user: User = session.query(User).filter(User.email == email).first() if not user: raise NotFoundException(detail="No account found for email.") if user.is_banned: raise BannedUserException() user.reset_uuid = uuid.uuid4() session.commit() if not send_message( recipient=user.email, template_id=settings.sendgrid_reset_template, data={ "reset_token": str(user.reset_uuid), "email": user.email }, ): if settings.debug: logger.debug(f"RESET TOKEN FOR {email}: {user.reset_uuid}") raise APIException( detail= "Unable to send password reset email; please contact Skaak#0007 on Discord." ) return { "detail": "A link to reset your password has been sent to your email!" }
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
def test_get_releases(client: TestClient, session: db.Session): """Releases endpoint must return a list of all releases""" master_set = Release(name="Master Set") master_set.is_public = True session.add(master_set) session.commit() response = client.get("/v2/releases") assert response.status_code == status.HTTP_200_OK assert len(response.json()) == 1
def test_login_required_banned_user(client: TestClient, session: db.Session): """login_required dependency does not allow banned users""" user, token = utils.create_user_token(session) user.is_banned = True session.commit() response = client.get( "/v2/players/me", headers={"Authorization": f"Bearer {token}"} ) assert response.status_code == status.HTTP_403_FORBIDDEN, response.json()
def test_get_private_share_deleted( client: TestClient, session: db.Session, user1, deck1 ): """Deleted decks must throw an error when accessing their direct share UUID""" snapshot2 = create_snapshot_for_deck(session, user1, deck1) snapshot2.is_deleted = True session.commit() response = client.get(f"/v2/decks/shared/{snapshot2.direct_share_uuid}") assert response.status_code == status.HTTP_404_NOT_FOUND
def test_delete_deck_legacy(client: TestClient, session: db.Session, user_token): """Requests to delete a legacy deck must fail""" user, token = user_token deck = create_deck_for_user(session, user) deck.is_legacy = True session.commit() response = client.delete(f"/v2/decks/{deck.id}", headers={"Authorization": f"Bearer {token}"}) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_delete_deck_already_deleted(client: TestClient, session: db.Session, user_token): """Must return success if deck was previously deleted""" user, token = user_token deck = create_deck_for_user(session, user) deck.is_deleted = True session.commit() response = client.delete(f"/v2/decks/{deck.id}", headers={"Authorization": f"Bearer {token}"}) assert response.status_code == status.HTTP_204_NO_CONTENT
def save_collection( collection: List[str], session: db.Session = Depends(get_session), current_user: "******" = Depends(login_required), ): """Update the user's collection in place. PUT a list of release slugs to set them as the user's collection (e.g. `['master-set', 'the-frostdale-giants']`. **This is not a patch!** You must pass the entire list of the user's collections every time. """ # Clear out our existing releases session.query(UserRelease).filter( UserRelease.user_id == current_user.id).delete() session.commit() release_ids = ((session.query(Release.id).filter( Release.is_legacy.is_(False), Release.is_public.is_(True), Release.stub.in_(collection), ).all()) if collection else None) if release_ids: for row in release_ids: session.add(UserRelease(user_id=current_user.id, release_id=row.id)) session.commit() query = get_releases_query(session=session, current_user=current_user) return query.all()
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
def update_my_data( updates: schema.UserSelfIn, current_user: "******" = Depends(login_required), session: db.Session = Depends(get_session), ): """Update user information for the logged-in user.""" update_dict = updates.dict(exclude_unset=True) for key, value in update_dict.items(): setattr(current_user, key, value) session.commit() return current_user
def deck_to_dict(session: db.Session, deck: Deck, include_comment_entity_id=False) -> dict: """Converts a Deck object into an output dict using as few queries as possible.""" needed_cards = set() needed_cards.add(deck.phoenixborn_id) deck_cards = session.query(DeckCard).filter( DeckCard.deck_id == deck.id).all() for deck_card in deck_cards: needed_cards.add(deck_card.card_id) deck_dice = session.query(DeckDie).filter(DeckDie.deck_id == deck.id).all() # And finally we need to fetch all top-level conjurations card_id_to_conjurations = get_conjuration_mapping(session=session, card_ids=needed_cards) # Now that we have root-level conjurations, we can gather all our cards and generate deck output cards = session.query(Card).filter(Card.id.in_(needed_cards)).all() card_id_to_card = {x.id: x for x in cards} deck_dict = generate_deck_dict( deck=deck, card_id_to_card=card_id_to_card, card_id_to_conjurations=card_id_to_conjurations, deck_cards=deck_cards, deck_dice=deck_dice, ) deck_dict["description"] = deck.description deck_dict["is_public"] = deck.is_public deck_dict["is_snapshot"] = deck.is_snapshot if include_comment_entity_id: # This is an implicit SQL lookup, but it's going to require a lookup either way, so meh deck_dict["comments_entity_id"] = (deck.source.entity_id if deck.source_id else deck.entity_id) # If we are including first five information, grab that now first_five = [] effect_costs = [] tutor_map = {} # This is another implicit SQL lookup, but again it requires a lookup either way for selected_card in deck.selected_cards: card = card_id_to_card.get(selected_card.card_id) # This situation should theoretically never happen, but just in case... if not card: continue if selected_card.is_first_five: first_five.append(card.stub) if selected_card.is_paid_effect: effect_costs.append(card.stub) if selected_card.tutor_card_id: tutor_card = card_id_to_card.get(selected_card.tutor_card_id) if tutor_card: tutor_map[tutor_card.stub] = card.stub deck_dict["first_five"] = first_five deck_dict["effect_costs"] = effect_costs deck_dict["tutor_map"] = tutor_map return deck_dict
def test_clone_deck(client: TestClient, session: db.Session, deck, user_token): """Can clone own deck""" user, token = user_token # Verify that we have three "decks" (original deck, private snapshot, public snapshot) assert session.query(Deck).filter(Deck.user_id == user.id).count() == 3 response = client.get( f"/v2/decks/{deck.id}/clone", headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == status.HTTP_200_OK # Check that we now have two more decks than before: new deck, and source snapshot assert session.query(Deck).filter(Deck.user_id == user.id).count() == 5
def test_delete_public_snapshot(client: TestClient, session: db.Session, user_token, deck): """Must properly clean up stream entries when deleting a public snapshot""" user, token = user_token snapshot = create_snapshot_for_deck(session, user, deck, is_public=True) assert session.query(Stream).count() == 1 response = client.delete(f"/v2/decks/{snapshot.id}", headers={"Authorization": f"Bearer {token}"}) assert response.status_code == status.HTTP_204_NO_CONTENT assert session.query(Stream).count() == 0 session.refresh(snapshot) assert snapshot.is_deleted == True
def test_post_snapshot_deleted_deck(client: TestClient, session: db.Session, user_token): """Must not allow creating snapshots for a deleted deck""" user, token = user_token deck = create_deck_for_user(session, user) deck.is_deleted = True session.commit() response = client.post( f"/v2/decks/{deck.id}/snapshot", headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_reset_password_bad_passwords(client: TestClient, session: db.Session): """Password must match confirmation value""" user, _ = utils.create_user_token(session) user.reset_uuid = uuid.uuid4() session.commit() password = utils.generate_random_chars(8) password2 = f"a{password}" response = client.post( f"/v2/reset/{user.reset_uuid}", json={"password": password, "password_confirm": password2}, ) assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
def test_patch_release_non_admin(client: TestClient, session: db.Session): """Patching a release must require admin access""" master_set = Release(name="Master Set") session.add(master_set) session.commit() user, token = create_user_token(session) response = client.patch( f"/v2/releases/{master_set.stub}", json={"is_public": True}, headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_put_deck_deleted(client: TestClient, session: db.Session, user_token): """Must not allow saving over a deleted deck""" user, token = user_token deck = create_deck_for_user(session, user) deck.is_deleted = True session.commit() valid_deck = _valid_deck_dict(session) valid_deck["id"] = deck.id response = client.put("/v2/decks", json=valid_deck, headers={"Authorization": f"Bearer {token}"}) assert response.status_code == status.HTTP_400_BAD_REQUEST
def check_moniting_state_icmp(i): while 1: #try: session = Session() ins = queue_moniting.get(True) print "Greenlets %s got : %s" % (i,time.asctime()), " " , ins instance_result = dict() moniting_state = eval(ins['moniting_state']) ipaddress = eval(ins['ipaddress']) ping = moniting_state['ping'] arp = moniting_state['arp'] tcp = moniting_state['tcp'] udp = moniting_state['udp'] if ipaddress: instance_result['uuid'] = ins['uuid'] for ip in ipaddress: instance_result[ip] = dict() if ping: instance_result[ip]['ping'] = 1 if icmp_checker_gevent.check_icmp(ip) == True else 0 #if arp: # instance_result[ip]['arp'] = 1 if arp_checker_gevent.check_arp(ip) == True else 0 #if tcp: # instance_result[ip]['tcp'] = dict() # if isinstance(tcp,unicode): # # if tcp is unicode string, means that's only one port. # port = tcp # instance_result[ip]['tcp'][port] = 1 if tcp_checker_gevent.check_tcp(ip,int(port)) == True else 0 # else: # for port in tcp: # instance_result[ip]['tcp'][port] = 1 if tcp_checker_gevent.check_tcp(ip,int(port)) == True else 0 ##if udp: # instance_result[ip]['udp'] = dict() # if isinstance(udp,unicode): # # if tcp is unicode string, means that's only one port. # port = udp # instance_result[ip]['udp'][port] = 1 if udp_checker.checker_udp(ip,int(port)) == True else 0 # else: # for port in udp: # instance_result[ip]['udp'][port] = 1 if udp_checker.checker_udp(ip,int(port)) == True else 0 print "Greenlets moniting %s got : %s" % (i,time.asctime()) , instance_result # send notification to user, use http or sms send_notification(instance_result,'moniting') # save last notification, used in next time save_one_notification(instance_result,'moniting') q = session.query(Instances).filter(Instances.uuid==ins['uuid']) if q.all(): q.update( {Instances.moniting_state:simplejson.dumps(instance_result)} ) session.commit()
def test_get_legacy_card(client: TestClient, session: db.Session): """Must be able to read JSON for a legacy card""" # This is handled by a migration normally (legacy cards can't normally be created by this API) card = (session.query(Card).filter(Card.stub == "example-phoenixborn", Card.is_legacy == True).first()) card.json["release"]["is_legacy"] = True card.json["is_legacy"] = True db.flag_modified(card, "json") session.commit() response = client.get("/v2/cards/example-phoenixborn", params={"show_legacy": True}) assert response.status_code == status.HTTP_200_OK assert response.json()["is_legacy"] == True, response.json()
def test_post_snapshot_precon_non_public(client: TestClient, session: db.Session): """Must stop creation of preconstructed release if not a public snapshot""" admin, token = create_user_token(session) admin.is_admin = True session.commit() deck = create_deck_for_user(session, admin, release_stub="expansion") response = client.post( f"/v2/decks/{deck.id}/snapshot", json={"preconstructed_release": "expansion"}, headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == status.HTTP_400_BAD_REQUEST
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
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
def test_reset_password(client: TestClient, session: db.Session): """Password reset must reset the password""" user, _ = utils.create_user_token(session) user.reset_uuid = uuid.uuid4() session.commit() new_password = utils.generate_random_chars(8) original_hash = user.password response = client.post( f"/v2/reset/{user.reset_uuid}", json={"password": new_password, "password_confirm": new_password}, ) assert response.status_code == status.HTTP_200_OK session.refresh(user) assert original_hash != user.password
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
def test_delete_latest_public_snapshot(client: TestClient, session: db.Session, user_token, deck): """Must properly revert to older snapshot in stream when deleting a public snapshot""" user, token = user_token snapshot1 = create_snapshot_for_deck(session, user, deck, is_public=True) snapshot2 = create_snapshot_for_deck(session, user, deck, is_public=True) assert session.query(Stream).count() == 1 response = client.delete(f"/v2/decks/{snapshot2.id}", headers={"Authorization": f"Bearer {token}"}) assert response.status_code == status.HTTP_204_NO_CONTENT stream_entry = session.query(Stream).first() assert stream_entry.entity_id == snapshot1.entity_id session.refresh(snapshot2) assert snapshot2.is_deleted == True
class check_notification_state(threading.Thread): """ check moniting state for instance """ def __init__(self): super(check_notification_state,self).__init__() self.daemon = True self.session = Session() def run(self): while 1: ins_opition = queue_notification.get(True) sql = """ SELECT result FROM cloud_result WHERE TIME = ( SELECT MAX( TIME ) FROM cloud_result ) AND uuid IN ( '%s' ) """ % ins_opition['uuid'] result = raw_sql(sql) # if result is empty, skip current loop. if not result: continue # analyst notification in another function ret = analyst_notification_result(result,ins_opition) if not ret: continue q = self.session.query(Instances).filter(Instances.uuid==ins_opition['uuid']) if q.all(): q.update( {Instances.notification_state:simplejson.dumps(ret)} ) self.session.commit()
def __init__(self): super(check_notification_state,self).__init__() self.daemon = True self.session = Session()
def __init__(self): super(check_moniting_state,self).__init__() self.daemon = True self.session = Session()
class check_moniting_state(threading.Thread): """ check moniting state for instance """ def __init__(self): super(check_moniting_state,self).__init__() self.daemon = True self.session = Session() def run(self): while 1: #try: ins = queue_moniting.get(True) instance_result = dict() moniting_state = eval(ins['moniting_state']) ipaddress = eval(ins['ipaddress']) ping = moniting_state['ping'] arp = moniting_state['arp'] tcp = moniting_state['tcp'] udp = moniting_state['udp'] if ipaddress: instance_result['uuid'] = ins['uuid'] for ip in ipaddress: instance_result[ip] = dict() if ping: instance_result[ip]['ping'] = 1 if icmp_checker.check_icmp(ip) == True else 0 if arp: instance_result[ip]['arp'] = 1 if arp_checker.check_arp(ip) == True else 0 if tcp: instance_result[ip]['tcp'] = dict() if isinstance(tcp,unicode): # if tcp is unicode string, means that's only one port. port = tcp instance_result[ip]['tcp'][port] = 1 if tcp_checker.check_tcp(ip,int(port)) == True else 0 else: for port in tcp: instance_result[ip]['tcp'][port] = 1 if tcp_checker.check_tcp(ip,int(port)) == True else 0 if udp: instance_result[ip]['udp'] = dict() if isinstance(udp,unicode): # if tcp is unicode string, means that's only one port. port = udp instance_result[ip]['udp'][port] = 1 if udp_checker.checker_udp(ip,int(port)) == True else 0 else: for port in udp: instance_result[ip]['udp'][port] = 1 if udp_checker.checker_udp(ip,int(port)) == True else 0 # send notification to user, use http or sms send_notification(instance_result,'moniting') # save last notification, used in next time save_one_notification(instance_result,'moniting') q = self.session.query(Instances).filter(Instances.uuid==ins['uuid']) if q.all(): q.update( {Instances.moniting_state:simplejson.dumps(instance_result)} ) self.session.commit() #except: # pass # dont forget to close session at the end self.session.close()