예제 #1
0
def register(username: str, password: str):
    profile = Profile.get_or_none(Profile.username == username)
    if profile is not None:
        raise BadRequest('A user with this username already exists')
    hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
    profile = Profile.create(
        username=username,
        hashed_password=hashed,
    )
    global_game = Game.get_or_none(Game.name == 'Global Indefinite')
    GameProfile.create(game=global_game,
                       profile=profile,
                       cash=global_game.starting_cash)
    global_game = Game.get_or_none(Game.name == 'Global Timed')
    GameProfile.create(game=global_game,
                       profile=profile,
                       cash=global_game.starting_cash)
    send_notification(profile, 'Welcome to Fortune!')
    send_notification(
        profile,
        'Click the Play button in the menubar on top to create a new game.')
    send_notification(
        profile,
        'To adjust account options, see achiements, and add friends, click on your username on the top and select Profile'
    )
    return create_auth_token(profile)
예제 #2
0
def create_request(requester_name, requestee_name, status):
    requester_profile = Profile.get_or_none(Profile.username == requester_name)
    requestee_profile = Profile.get_or_none(Profile.username == requestee_name)
    if requester_profile is None:
        raise BadRequest('Could not find requester')
    if requestee_profile is None:
        send_notification(requester_profile,
                          f'User {requestee_name} does not exist.')
        raise BadRequest('Could not find requestee')
    if requester_profile == requestee_profile:
        send_notification(requester_profile, f'Cannot friend yourself!')
        raise BadRequest('Cannot friend self')
    check_duplicates = Friends.get_or_none(
        (Friends.requester == requester_profile)
        & (Friends.requestee == requestee_profile))
    if check_duplicates is not None:
        send_notification(
            requester_profile,
            f'Friend request to {requestee_profile.username} has already been created'
        )
        raise BadRequest('Friend request has already been made')
    req = Friends.create(requester=requester_profile,
                         requestee=requestee_profile,
                         status=status)
    send_notification(
        requester_profile,
        f'Friend request to {requestee_profile.username} has been sent!')
    send_notification(
        requestee_profile,
        f'{requester_profile.username} has sent you a friend request!')
    return req
예제 #3
0
def change_username(profile_id: int, username: str):
    profile = Profile.get_or_none(Profile.username == username)
    if profile is not None:
        raise BadRequest('A user with this username already exists')
    try:
        update_username = Profile.update({
            Profile.username: username
        }).where(Profile.id == profile_id)
        update_username.execute()
    except Exception as e:
        raise BadRequest('Failure to change username: {}'.format(str(e)))
예제 #4
0
def ban_user(profile_id: int):
    rows = Profile.update({
        Profile.is_banned: True
    }).where(Profile.id == profile_id).execute()
    if rows == 0:
        raise BadRequest("Cannot ban user")

    profile = Profile.get_or_none(Profile.id == profile_id)
    if not profile:
        raise BadRequest("Profile not found")
    print("BANNED PROFILE IS BANNED:", profile.is_banned)

    broadcast(profile, "ban",
              "Your account has been banned for violating our policy.", True)
예제 #5
0
def set_skin(readable, model, profile: Profile):
    try:
        image: Image = Image.open(readable)
    except (FileNotFoundError, UnidentifiedImageError, ValueError):
        # May be inconsistent with official API
        return INVALID_IMAGE.dual

    try:
        profile.update_skin(image, model)
    except ValueError:
        # May be inconsistent with official API
        return INVALID_SKIN.dual

    return "", 204
예제 #6
0
def call(program, argv):
    parser = argparse.ArgumentParser(prog=program)

    parser.add_argument("dbid", help="new profile's account DBID", type=int)
    parser.add_argument("name", help="new profile's username")
    parser.add_argument("agent", help="new profile's agent")
    parser.add_argument("-u", "--uuid", help="new profile's UUID", type=UUID)

    args = parser.parse_args(argv)

    input_uuid = args.uuid if args.uuid is not None else uuid4()

    account: Account = Account.get(id=args.dbid)
    if account is None:
        print("No account matches that DBID!")
        exit(1)

    try:
        profile = Profile.create(uuid=input_uuid,
                                 agent=args.agent,
                                 account=account,
                                 name=args.name)
    except ExistsException:
        print("Name not available.")
        exit(1)

    try:
        commit()
    except Exception as e:
        print(str(e))
        exit(1)

    print(profile)
예제 #7
0
def call(program, argv):
    parser = argparse.ArgumentParser(prog=program)

    parser.add_argument("name", help="profile name")
    parser.add_argument("-t",
                        "--time",
                        help="timestamp of past time",
                        type=int)
    parser.add_argument("--unix",
                        help="show timestamps as integer",
                        action="store_true")

    args = parser.parse_args(argv)

    if args.time is None:
        args.time = datetime.utcnow()

    event = Profile.that_owned_name_at(args.name, args.time)

    print(f"History of {args.name}")

    if event is None:
        print(f"No profile owned that name at {args.time}!")
    else:
        print(f"Owner of {event.name} @ {args.time}: {event.profile}")

    events = ProfileNameEvent.select(lambda x: x.name == args.name
                                     or x.name_upper == args.name.upper()
                                     or x.name_lower == args.name.lower())\
        .order_by(desc(ProfileNameEvent.active_from))

    for old_event in events:
        print(old_event)
예제 #8
0
 def test_get_coins_with_invalid_time_span(self):
     profile = Profile.get_or_none(Profile.username == 'theusername')
     GameProfile.create(game=1, profile=profile, cash=10000)
     res = self.client.get(
         '/game/1/coins?timeSpan=6&sortBy=0&numPerPage=10&pageNum=1',
         headers={'Authorization': 'Bearer ' + self.token})
     self.assertEqual(int(HTTPStatus.BAD_REQUEST), res._status_code)
예제 #9
0
 def setUp(self):
     super().setUp()
     with db.atomic() as txn:
         profile = Profile.create(username='******',
                                  hashed_password='******')
         self.token = AuthToken.create(profile=profile,
                                       token='thevalidtoken').token
예제 #10
0
def json_and_response_code(uuid):
    if len(uuid) != 32:
        return "", 204

    try:
        uuid_object = UUID(uuid)
    except ValueError:
        return "", 204

    profile = Profile.get(uuid=uuid_object)

    if profile is None:
        return "", 204

    history = []

    for event in profile.profile_name_events.order_by(desc(ProfileNameEvent.active_from)):
        event: ProfileNameEvent
        if event.is_initial_name:
            history.append({
                "name": event.name
            })
        else:
            history.append({
                "name": event.name,
                "changedToAt": int(event.active_from.timestamp())
            })

    return jsonify(history), 200
예제 #11
0
def join_mcserver(request, textures_host):
    username, server_hash, ip = request.args.get("username"), request.args.get(
        "serverId"), request.args.get("ip")
    if username is None or server_hash is None:
        # May be inconsistent with official API
        return NULL_MESSAGE.dual

    profile = Profile.get_profile_with_name(username)
    if profile is None:
        # May be inconsistent with official API
        return MCSERVER_INVALID_PROFILE.dual

    session = MCServerSession.get(
        lambda x: x.profile == profile and x.server_hash == server_hash)

    if session is None:
        # May be inconsistent with official API
        return MCSERVER_INVALID_SESSION.dual

    if ip is not None and session.client_side_ip != ip:
        # May be inconsistent with official API
        return MCSERVER_DIFFERENT_IP.dual

    session.delete()

    return jsonify(get_public_profile_details(profile, False,
                                              textures_host)), 200
예제 #12
0
def call(program, argv):
    parser = argparse.ArgumentParser(prog=program)

    parser.add_argument("dbid", help="DBID of profile", type=int)
    parser.add_argument("--unix",
                        help="show timestamps as integer",
                        action="store_true")

    args = parser.parse_args(argv)

    profile: Profile = Profile.get(id=args.dbid)
    if profile is None:
        print("No profile matches that DBID!")
        exit(1)

    print(f"History of {profile}")
    print(
        f"Current name styles: {profile.name}, {profile.name_upper}, {profile.name_lower}"
    )

    for event in profile.profile_name_events.order_by(
            desc(ProfileNameEvent.active_from)):
        if args.unix:
            print(event.repr_timestamp())
        else:
            print(event)
예제 #13
0
    def test_user_automatically_joins_new_global_time_game(self):
        # register user
        res = self.client.post('/auth/register',
                               data=json.dumps({
                                   'username': '******',
                                   'password': '******',
                                   'password': '******',
                               }),
                               headers={'Content-Type': 'application/json'})
        self.assertEqual(200, res._status_code)
        game_before_check = Game.get(Game.name == 'Global Timed')
        game_before_check.ends_at = datetime.utcnow()
        game_before_check.save()
        # assert deletes old GameProfile
        profile = Profile.get_by_id(1)
        qry = GameProfile.select().join(Game).where(
            (GameProfile.profile == profile) & (Game.name == 'Global Timed'))
        self.assertEqual(2, len(profile.game_profiles)
                         )  # should have 2: global timed and indefinite
        self.assertEqual(1, qry.count())  # just to make sure
        gp_old = qry.get()

        check_global_timed_game()

        # assert creates new GameProfile
        qry = GameProfile.select().join(Game).where(
            (GameProfile.profile == profile) & (Game.name == 'Global Timed'))
        self.assertEqual(1, qry.count())
        gp_new = qry.get()

        # but the ids should not be the same
        self.assertNotEqual(gp_old.id, gp_new.id)
예제 #14
0
def call(program, argv):
    parser = argparse.ArgumentParser(prog=program)

    parser.add_argument("dbid", help="DBID of profile", type=int)
    parser.add_argument("timestamp", help="timestamp", type=int)

    args = parser.parse_args(argv)

    profile: Profile = Profile.get(id=args.dbid)
    if profile is None:
        print("No profile matches that DBID!")
        exit(1)

    try:
        event = profile.owned_name_at(datetime.utcfromtimestamp(
            args.timestamp))
    except OSError:
        print("Invalid timestamp.")
        exit(1)

    if event is None:
        print("This profile didn't have a name at that time.")
        exit(1)

    print(event)
예제 #15
0
def login(username: str, password: str):
    profile = Profile.get_or_none(Profile.username == username)
    if profile is None:
        raise BadRequest('A user with this username does not exist')
    if profile.is_banned:
        raise BadRequest("This user has been banned.")
    if not bcrypt.checkpw(password.encode(), profile.hashed_password.encode()):
        raise BadRequest('Incorrect password')
    return create_auth_token(profile)
예제 #16
0
def accept_request(requester_name, requestee_name):
    requester_profile = Profile.get_or_none(Profile.username == requester_name)
    requestee_profile = Profile.get_or_none(Profile.username == requestee_name)
    if requester_profile is None:
        raise BadRequest('Could not find requester')
    if requestee_profile is None:
        raise BadRequest('Could not find requestee')
    req = Friends.get_or_none((Friends.requester == requester_profile)
                              & (Friends.requestee == requestee_profile))
    if req is None:
        raise BadRequest('Could not find request')
    req.status = 1
    other_way_friendship = Friends.create(requester=requestee_profile,
                                          requestee=requester_profile,
                                          status=1)
    send_notification(
        requester_profile,
        f'{requestee_profile.username} has accepted your friend request!')
    return req
예제 #17
0
def send(profile):
    validated_data: dict = FriendsSerializer.deserialize(request.json)
    requester_name = validated_data['requester']
    requestee_name = validated_data['requestee']
    status = validated_data['status']
    friend_req = create_request(requester_name, requestee_name, status)
    if friend_req is None:
        raise BadRequest('Could not create request')
    pending = get_pending_by_profile(Profile.get_or_none(Profile.username == requestee_name))
    return jsonify(PendingList.serialize({'pending': pending,}))
예제 #18
0
def json_and_response_code(request):
    if "clientToken" not in request.json or request.json["clientToken"] is None:
        return NULL_CLIENT_TOKEN.dual

    if "accessToken" not in request.json or request.json["accessToken"] is None:
        return NULL_ACCESS_TOKEN.dual

    access_token = AccessToken.from_token(request.json["accessToken"])
    try:
        if access_token is None or access_token.client_token.uuid != UUID(
                request.json["clientToken"]):
            return INVALID_TOKEN.dual
    except ValueError:
        return INVALID_UUID.dual

    if "selectedProfile" in request.json:
        try:
            _selected_uuid = UUID(request.json["selectedProfile"]["id"])
        except ValueError:
            return INVALID_UUID.dual
        new_profile = Profile.get(
            lambda x: x.uuid == _selected_uuid and x.name == request.json[
                "selectedProfile"][
                    "name"] and x.account == access_token.client_token.account)
        if new_profile is None:
            return PROFILE_NOT_FOUND.dual
    else:
        new_profile = access_token.profile

    new_access_token = AccessToken(
        client_token=access_token.client_token,
        profile=new_profile,
    )

    access_token.delete()

    response_data = {
        "accessToken": jwt_encode(new_access_token.format(), key="").decode(),
        "clientToken": request.json["clientToken"],
    }

    if new_access_token.profile:
        response_data["selectedProfile"] = {
            "id": new_access_token.profile.uuid.hex,
            "name": new_access_token.profile.name
        }

    if "requestUser" in request.json and request.json["requestUser"]:
        response_data["user"] = {
            "id": new_access_token.client_token.account.uuid.hex,
            "username": new_access_token.client_token.account.username
        }

    return jsonify(response_data), 200
예제 #19
0
def call(program, argv):
    parser = ArgumentParser(prog=program)

    parser.add_argument("dbid", help="DBID of profile", type=int)

    sources = parser.add_mutually_exclusive_group(required=True)
    sources.add_argument("-u", "--url", help="url of skin", dest="url")
    sources.add_argument("-f", help="file path of skin", dest="path")
    sources.add_argument("--delete",
                         help="reset profile skin",
                         action="store_true")

    parser.add_argument("--slim", help="slim model", action="store_true")

    args = parser.parse_args(argv)

    profile: Profile = Profile.get(id=args.dbid)
    if profile is None:
        print("No profile matches that DBID!")
        exit(1)

    if args.url is not None:
        fd = BytesIO(get(args.url).content)
    elif args.path is not None:
        fd = Path(args.path)
    elif not args.delete:
        print("You must specify a file!")
        exit(1)

    if args.delete:
        profile.reset_skin()
    else:
        try:
            image: Image = Image.open(fd)
        except (FileNotFoundError, UnidentifiedImageError, ValueError):
            print(INVALID_IMAGE.message)
            exit(1)

        try:
            profile.update_skin(image, "slim" if args.slim else "")
        except ValueError:
            print(INVALID_SKIN.message)
            exit(1)

    try:
        commit()
    except Exception as e:
        print(e)
        exit(1)

    if not args.delete:
        print(f"Texture name: {profile.profile_skin.name}")
예제 #20
0
파일: v1.py 프로젝트: raziqraif/fortune
def up(db):
    with db.atomic():
        migrator = PostgresqlMigrator(db)
        db.bind(MODELS, bind_refs=False, bind_backrefs=False)
        db.create_tables(MODELS)
        if Coin.get_or_none(Coin.id == 1) is None:
            Coin.create(name='Bitcoin', symbol='BTC')
            Coin.create(name='Ethereum', symbol='ETH')
            Coin.create(name='Litecoin', symbol='LTC')
            Coin.create(name='Coin 3', symbol='CO3')
            Coin.create(name='Coin 4', symbol='CO4')
            Coin.create(name='Coin 5', symbol='CO5')

        global_indef = Game.create(name='Global Indefinite',
                                   starting_cash=10000.00,
                                   shareable_link='INDEF',
                                   shareable_code='INDEF',
                                   ends_at=None)

        # insert achievements into database
        Achievement.create(
            name="Win", description="Finish in first place in a private game")
        Achievement.create(
            name="Double net worth",
            description="Achieved by doubling your net worth in a game")
        Achievement.create(name="Identity Crisis",
                           description="Change your username")

        # insert goals into database
        Goal.create(name="Entrepreneur", description="Create a private game")

        all_coins = Coin.select()
        for coin in all_coins:
            GameCoin.create(game=global_indef, coin=coin)

        global_timed = Game.create(name='Global Timed',
                                   starting_cash=10000.00,
                                   shareable_link='TIMED',
                                   shareable_code='TIMED',
                                   ends_at=datetime.utcnow() +
                                   timedelta(minutes=1))
        # CHANGEME for devel purposes, making it 1 min for now
        GameCoin.create(game=global_timed, coin=Coin.get())

        # from auth.services import register
        hashed = bcrypt.hashpw("admin".encode(), bcrypt.gensalt()).decode()
        admin = Profile.create(username="******",
                               hashed_password=hashed,
                               is_admin=True)
        # Required so that admin can still view graphs in the landing page
        GameProfile.create(profile=admin, game=global_indef, cash=0.0)
예제 #21
0
def json_and_response_code(request):
    if len(request.json) > 10:
        return OVER_PROFILE_LIMIT.dual

    uuids = []

    for name in request.json:
        profile = Profile.get_profile_with_name(name)
        if profile is None:
            continue

        uuids.append({"id": profile.uuid.hex, "name": profile.name})

    return jsonify(uuids), 200
예제 #22
0
 def test_buy_coin_without_cash(self):
     profile = Profile.get_or_none(Profile.username == 'theusername')
     GameProfile.create(game=1, profile=profile, cash=0)
     GameCoin.create(game=1, coin=1)
     Ticker.create(coin=1, price=10, price_change_day_pct=1.1)
     res = self.client.post(
         '/game/1/coin',
         data=json.dumps({
             'coinId': '1',
             'coinAmount': '1',
         }),
         content_type='application/json',
         headers={'Authorization': 'Bearer ' + self.token})
     self.assertEqual(int(HTTPStatus.BAD_REQUEST), res._status_code)
예제 #23
0
def change_password(profile: Profile, old_password: str, new_password: str):
    if not bcrypt.checkpw(old_password.encode(),
                          profile.hashed_password.encode()):
        raise BadRequest('Incorrect old password')
    hashed_new_password = bcrypt.hashpw(new_password.encode(),
                                        bcrypt.gensalt()).decode()
    try:
        update_password = Profile.update({
            Profile.hashed_password:
            hashed_new_password
        }).where(Profile.id == profile.id)
        update_password.execute()
    except Exception as e:
        raise BadRequest('Failure to change password: {}'.format(str(e)))
예제 #24
0
 def setUp(self):
     super().setUp()
     with db.atomic() as txn:
         #don't need to create a game, migrations/v1.py gets run before every test
         #Coin.create(id=1, name='Bitcoin', symbol='BTC')
         Game.create(name='Game',
                     starting_cash=10000.00,
                     shareable_link='aaaabbbbccccdddd',
                     shareable_code='aaaa',
                     ends_at=(datetime.utcnow().replace(tzinfo=pytz.utc) +
                              timedelta(days=7)).isoformat())
         profile = Profile.create(username='******',
                                  hashed_password='******')
         self.token = AuthToken.create(profile=profile,
                                       token='thevalidtoken').token
예제 #25
0
def send_notification_to_all(message: str):
    if socketio is None:
        raise Exception('Tried to emit but socketio is not initialized!')

    profiles = Profile.select().where(~Profile.is_admin).execute()
    notifications = [(profile.id, message) for profile in profiles]
    for batch in chunked(notifications, 100):
        Notification.insert_many(
            batch, fields=[Notification.profile,
                           Notification.content]).execute()

    # LOOKATME: Seems slow
    for profile in profiles:
        if not profile.socket_id:
            continue
        socketio.emit('notification', message, room=profile.socket_id)
예제 #26
0
def json_and_response_code(request, uuid, textures_host):
    try:
        uuid_object = UUID(uuid)
    except ValueError:
        return "", 204

    profile = Profile.get(uuid=uuid_object)
    if profile is None:
        return "", 204

    unsigned = request.args.get("unsigned")
    if unsigned is not None and unsigned == "false":
        return jsonify(
            get_public_profile_details(profile, False, textures_host)), 200
    return jsonify(get_public_profile_details(profile, True,
                                              textures_host)), 200
예제 #27
0
 def test_liquefy_success(self):
     profile = Profile.get_or_none(Profile.username == 'theusername')
     game_profile = GameProfile.create(game=1, profile=profile, cash=0)
     GameCoin.create(game=1, coin=1)
     GameProfileCoin.create(game_profile=game_profile,
                            coin=1,
                            coin_amount=2)
     Ticker.create(
         coin=1,
         price=10,
         captured_at=(datetime.utcnow()).isoformat(),
         price_change_day_pct=1.1,
     )
     res = self.client.delete(
         '/game/1/coins', headers={'Authorization': 'Bearer ' + self.token})
     self.assertEqual(int(HTTPStatus.OK), res._status_code)
예제 #28
0
def json_and_response_code(request, username):
    if "at" not in request.args:
        at = datetime.utcnow()
    else:
        try:
            at = datetime.utcfromtimestamp(int(request.args["at"]))
        except (ValueError, OSError):
            return INVALID_TIMESTAMP.dual

    event = Profile.that_owned_name_at(username, at)
    if event is None:
        return "", 204

    return jsonify({
        "id": event.profile.uuid.hex,
        "name": event.profile.name
    }), 200
 def test_allows_correct_token(self, auth_token_mock):
     stub_profile = Profile(
         username='******',
         hashed_password='******',
     )
     stub_authtoken = AuthToken(
         profile=stub_profile,
         token='valid-token',
     )
     auth_token_mock.return_value = stub_authtoken
     m = Mock()
     m.headers.get.return_value = 'Bearer valid-token'
     with patch('auth.decorators.request', m):
         profile = route()
         self.assertEqual(stub_profile.username, profile.username)
         self.assertEqual(stub_profile.hashed_password,
                          profile.hashed_password)
     auth_token_mock.assert_called_with('valid-token')
예제 #30
0
 def test_get_coins_success(self):
     profile = Profile.get_or_none(Profile.username == 'theusername')
     GameProfile.create(game=1, profile=profile, cash=10000)
     GameCoin.create(
         game=1,
         coin=1,
     )
     for coin in Coin.select():
         Ticker.create(
             coin=coin,
             price=30.0,
             captured_at=(datetime.utcnow()).isoformat(),
             price_change_day_pct=1.1,
         )
     res = self.client.get(
         '/game/1/coins?timeSpan=1&sortBy=0&numPerPage=10&pageNum=1',
         headers={'Authorization': 'Bearer ' + self.token})
     self.assertEqual(int(HTTPStatus.OK), res._status_code)