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 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_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 log_out( session: db.Session = Depends(get_session), jwt_payload: dict = Depends(get_auth_token), current_user: "******" = Depends(login_required), ): """Log a user out and revoke their JWT token's access rights. It's a good idea to invoke this whenever an authenticated user logs out, because tokens can otherwise be quite long-lived. """ # Do some quick clean-up to keep our table lean and mean; deletes any tokens that expired more than 24 hours ago session.query(UserRevokedToken).filter( UserRevokedToken.expires < dt.datetime.utcnow() - dt.timedelta(days=1)).delete(synchronize_session=False) session.commit() # Then add our newly revoked token expires_at = dt.datetime.fromtimestamp(jwt_payload["exp"], tz=dt.timezone.utc) # No need to do `.get("jti")` here because a missing JTI would result in a credentials error in the dependencies revoked_hex = jwt_payload["jti"] revoked_uuid = uuid.UUID(hex=revoked_hex) revoked_token = UserRevokedToken(revoked_uuid=revoked_uuid, user_id=current_user.id, expires=expires_at) session.add(revoked_token) session.commit() return {"detail": "Token successfully revoked."}
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_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 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_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_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_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 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 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 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_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 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_get_releases_public_only(client: TestClient, session: db.Session): """Releases list must only include public releases""" master_set = Release(name="Master Set") master_set.is_public = True session.add(master_set) session.add(Release(name="Unreleased")) session.commit() response = client.get("/v2/releases") assert response.status_code == status.HTTP_200_OK data = response.json() assert len(data) == 1 assert data[0]["stub"] == master_set.stub
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 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_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_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_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_admin_required_normal_user(client: TestClient, session: db.Session): """Non-admins cannot access admin_required dependency paths""" user1, token = utils.create_user_token(session) user2, _ = utils.create_user_token(session) user2.username = "******" session.commit() response = client.patch( f"/v2/players/{user2.badge}", headers={"Authorization": f"Bearer {token}"}, json={"username": "******", "moderation_notes": "Bad name."}, ) assert response.status_code == status.HTTP_403_FORBIDDEN, response.json() session.refresh(user2) assert user2.username == "oldname"
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_patch_release(client: TestClient, session: db.Session): """Patching a release to set it public must work""" master_set = Release(name="Master Set") session.add(master_set) session.commit() assert master_set.is_public == False admin, token = create_admin_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_200_OK session.refresh(master_set) assert master_set.is_public == True
def test_generate_badges_some_taken(session: db.Session, monkeypatch): """Unit test to simulate some badges being taken (recursion)""" user, _ = create_user_password(session) user.badge = "1234" session.commit() # Ensure our target badge is "randomly" generated the first time def _fake_badges(*args, **kwargs): # We only want to hijack this once monkeypatch.undo() return ["1234", "5678"] monkeypatch.setattr("api.services.user._random_badges", _fake_badges) badges = generate_badges(session, single=False, number=2) assert "5678" in badges
def test_put_releases_bad_release(client: TestClient, session: db.Session): """Putting a nonsense stub must work""" master_set = Release(name="Master Set") master_set.is_public = True session.add(master_set) session.commit() user, token = create_user_token(session) response = client.put( "/v2/releases/mine", json=["fake-set"], headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == status.HTTP_200_OK data = response.json() assert data[0]["stub"] == master_set.stub assert data[0]["is_mine"] == False
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()
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()