Example #1
0
def removeusercard(userid: int) -> Dict[str, Any]:
    # Cast the userID.
    userid = UserID(userid)

    # Grab card, convert it
    card = request.get_json()['card']
    try:
        cardid = CardCipher.decode(card)
    except CardCipherException:
        raise Exception('Invalid card number!')
    user = g.data.local.user.get_user(userid)
    # Make sure the user ID is valid
    if user is None:
        raise Exception('Cannot find user to update!')

    # Remove it from the user's account
    g.data.local.user.destroy_card(userid, cardid)

    # Return new card list
    return {
        'cards': [
            CardCipher.encode(card)
            for card in g.data.local.user.get_cards(userid)
        ],
    }
Example #2
0
def addusercard(userid: int) -> Dict[str, Any]:
    # Cast the userID.
    userid = UserID(userid)

    # Grab card, convert it
    card = request.get_json()['card']
    try:
        cardid = CardCipher.decode(card)
    except CardCipherException:
        raise Exception('Invalid card number!')
    user = g.data.local.user.get_user(userid)
    # Make sure the user ID is valid
    if user is None:
        raise Exception('Cannot find user to update!')

    # See if it is already claimed
    curuserid = g.data.local.user.from_cardid(cardid)
    if curuserid is not None:
        raise Exception('This card is already in use!')

    # Add it to the user's account
    g.data.local.user.add_card(userid, cardid)

    # Return new card list
    return {
        'cards': [
            CardCipher.encode(card)
            for card in g.data.local.user.get_cards(userid)
        ],
    }
Example #3
0
    def test_internal_cipher(self) -> None:
        test_ciphers = [
            ([0x68, 0xFC, 0xA5, 0x27, 0x00, 0x01, 0x04, 0xE0], [0xC7, 0xD0, 0xB3, 0x85, 0xAD, 0x1F, 0xD9, 0x49]),
            ([0x2C, 0x10, 0xA6, 0x27, 0x00, 0x01, 0x04, 0xE0], [0x33, 0xC6, 0xE6, 0x2E, 0x6E, 0x33, 0x38, 0x74]),
        ]

        for pair in test_ciphers:
            inp = bytes(pair[0])
            out = bytes(pair[1])
            encoded = CardCipher._encode(inp)  # type: ignore
            self.assertEqual(encoded, out, f"Card encode {encoded} doesn't match expected {out}")
            decoded = CardCipher._decode(out)  # type: ignore
            self.assertEqual(decoded, inp, f"Card decode {decoded} doesn't match expected {inp}")
Example #4
0
    def test_external_cipher(self) -> None:
        test_cards = [
            ("S6E523E30ZK7ML1P", "E004010027A5FC68"),
            ("78B592HZSM9E6712", "E004010027A6102C"),
        ]

        for card in test_cards:
            back = card[0]
            db = card[1]
            decoded = CardCipher.decode(back)
            self.assertEqual(decoded, db, f"Card DB {decoded} doesn't match expected {db}")
            encoded = CardCipher.encode(db)
            self.assertEqual(encoded, back, f"Card back {encoded} doesn't match expected {back}")
Example #5
0
def addcard() -> Dict[str, Any]:
    # Grab card, convert it
    card = request.get_json()['card']
    try:
        cardid = CardCipher.decode(card['number'])
    except CardCipherException:
        raise Exception('Invalid card number!')

    # Make sure it is our card
    userid = g.data.local.user.from_username(card['owner'])
    if userid is None:
        raise Exception('Cannot find user to add card to!')

    # See if it is already claimed
    curuserid = g.data.local.user.from_cardid(cardid)
    if curuserid is not None:
        raise Exception('This card is already in use!')

    # Add it to the user's account
    g.data.local.user.add_card(userid, cardid)

    # Return new card list
    return {
        'cards':
        [format_card(card) for card in g.data.local.user.get_all_cards()],
    }
Example #6
0
def searchusers() -> Dict[str, Any]:
    # Grab card, convert it
    searchdetails = request.get_json()['user_search']
    if len(searchdetails['card']) > 0:
        try:
            cardid = CardCipher.decode(searchdetails['card'])
            actual_userid = g.data.local.user.from_cardid(cardid)
            if actual_userid is None:
                # Force a non-match below
                actual_userid = UserID(-1)
        except CardCipherException:
            actual_userid = UserID(-1)
    else:
        actual_userid = None

    def match(user: User) -> bool:
        if actual_userid is not None:
            return user.id == actual_userid
        else:
            return True

    return {
        'users': [
            format_user(user) for user in g.data.local.user.get_all_users()
            if match(user)
        ],
    }
Example #7
0
def listcards() -> Dict[str, Any]:
    # Return new card list
    cards = [
        CardCipher.encode(card)
        for card in g.data.local.user.get_cards(g.userID)
    ]
    return {
        'cards': cards,
    }
Example #8
0
def main() -> None:
    parser = argparse.ArgumentParser(
        description=
        "A utility to convert between card IDs and back-of-card characters.")
    parser.add_argument(
        "number",
        help="card ID or back-of-card characters to convert.",
        type=str,
    )
    args = parser.parse_args()

    try:
        print(CardCipher.decode(args.number))
    except CardCipherException:
        try:
            back = CardCipher.encode(args.number)
            print(" ".join([back[i:(i + 4)] for i in range(0, len(back), 4)]))
        except CardCipherException:
            print('Bad card ID or back-of-card characters!')
Example #9
0
    def handle_system_convcardnumber_request(self, request: Node) -> Node:
        cardid = request.child_value('data/card_id')
        cardnumber = CardCipher.encode(cardid)

        system = Node.void('system')
        data = Node.void('data')
        system.add_child(data)

        system.add_child(Node.s32('result', 0))
        data.add_child(Node.string('card_number', cardnumber))
        return system
Example #10
0
def addcard() -> Dict[str, Any]:
    # Grab card, convert it
    card = request.get_json()['card']
    try:
        cardid = CardCipher.decode(card)
    except CardCipherException:
        raise Exception('Invalid card number!')

    # See if it is already claimed
    userid = g.data.local.user.from_cardid(cardid)
    if userid is not None:
        raise Exception('This card is already in use!')

    # Add it to this user's account
    g.data.local.user.add_card(g.userID, cardid)

    # Return new card list
    cards = [CardCipher.encode(card) for card in g.data.local.user.get_cards(g.userID)]
    return {
        'cards': cards,
    }
Example #11
0
def removecard() -> Dict[str, Any]:
    # Grab card, convert it
    card = request.get_json()['card']
    try:
        cardid = CardCipher.decode(card)
    except CardCipherException:
        raise Exception('Invalid card number!')

    # Make sure it is our card
    userid = g.data.local.user.from_cardid(cardid)
    if userid != g.userID:
        raise Exception('This card is not yours to delete!')

    # Remove it from this user's account
    g.data.local.user.destroy_card(g.userID, cardid)

    # Return new card list
    cards = [CardCipher.encode(card) for card in g.data.local.user.get_cards(g.userID)]
    return {
        'cards': cards,
    }
Example #12
0
def viewcards() -> Response:
    cards = [CardCipher.encode(card) for card in g.data.local.user.get_cards(g.userID)]
    return render_react(
        'Card Management',
        'account/cards.react.js',
        {
            'cards': cards,
        },
        {
            'addcard': url_for('account_pages.addcard'),
            'removecard': url_for('account_pages.removecard'),
            'listcards': url_for('account_pages.listcards'),
        },
    )
Example #13
0
def addbalance(arcadeid: int) -> Dict[str, Any]:
    credits = request.get_json()['credits']
    card = request.get_json()['card']

    # Make sure the arcade is valid
    arcade = g.data.local.machine.get_arcade(arcadeid)
    if arcade is None:
        raise Exception('Unable to find arcade to update!')
    if g.userID not in arcade.owners:
        raise Exception('You don\'t own this arcade, refusing to update!')

    try:
        cardid = CardCipher.decode(card)
        userid = g.data.local.user.from_cardid(cardid)
    except CardCipherException:
        userid = None

    if userid is None:
        raise Exception('Unable to find user by this card!')

    # Update balance
    balance = g.data.local.user.update_balance(userid, arcadeid, credits)
    if balance is not None:
        g.data.local.network.put_event(
            'paseli_transaction',
            {
                'delta': credits,
                'balance': balance,
                'reason': 'arcade operator adjustment',
            },
            userid=userid,
            arcadeid=arcadeid,
        )

    return {
        'balances': {
            balance[0]: balance[1]
            for balance in g.data.local.machine.get_balances(arcadeid)
        },
        'users':
        {user.id: user.username
         for user in g.data.local.user.get_all_users()},
        'events': [
            format_event(event) for event in g.data.local.network.get_events(
                arcadeid=arcadeid, event='paseli_transaction')
        ],
    }
Example #14
0
def format_card(card: Tuple[str, Optional[UserID]]) -> Dict[str, Any]:
    owner = None
    if card[1] is not None:
        user = g.data.local.user.get_user(card[1])
        if user is not None:
            owner = user.username
    try:
        return {
            'number': CardCipher.encode(card[0]),
            'owner': owner,
            'id': card[1],
        }
    except CardCipherException:
        return {
            'number': '????????????????',
            'owner': owner,
            'id': card[1],
        }
Example #15
0
def removecard() -> Dict[str, Any]:
    # Grab card, convert it
    card = request.get_json()['card']
    try:
        cardid = CardCipher.decode(card)
    except CardCipherException:
        raise Exception('Invalid card number!')

    # Make sure it is our card
    userid = g.data.local.user.from_cardid(cardid)

    # Remove it from the user's account
    g.data.local.user.destroy_card(userid, cardid)

    # Return new card list
    return {
        'cards': [format_card(card) for card in g.data.local.user.get_all_cards()],
    }
Example #16
0
    def verify_gametop_get_pdata(self, card_id: str, ref_id: str) -> int:
        call = self.call_node()

        # Construct node
        gametop = Node.void('gametop')
        call.add_child(gametop)
        gametop.set_attribute('method', 'get_pdata')
        retry = Node.s32('retry', 0)
        gametop.add_child(retry)
        data = Node.void('data')
        gametop.add_child(data)
        player = Node.void('player')
        data.add_child(player)
        player.add_child(Node.string('refid', ref_id))
        player.add_child(Node.string('datid', ref_id))
        player.add_child(Node.string('uid', card_id))
        player.add_child(Node.string('card_no', CardCipher.encode(card_id)))

        # Swap with server
        resp = self.exchange('', call)

        # Verify nodes that cause crashes if they don't exist
        return self.__verify_profile(resp)
Example #17
0
    def handle_eacoin_request(self, request: Node) -> Optional[Node]:
        """
        Handle PASELI requests. The game will check out a session at the beginning
        of the game, make PASELI purchases against that session, and then close it
        ad the end of of a game. This handler ensures that this works for all games.
        """
        method = request.attribute('method')

        if not self.config['paseli']['enabled']:
            # Refuse to respond, we don't have PASELI enabled
            print("PASELI not enabled, ignoring eacoin request")
            root = Node.void('eacoin')
            root.set_attribute('status', str(Status.NOT_ALLOWED))
            return root

        if method == 'checkin':
            root = Node.void('eacoin')
            cardid = request.child_value('cardid')
            pin = request.child_value('passwd')

            if cardid is None or pin is None:
                # Refuse to return anything
                print("Invalid eacoin checkin request, missing cardid or pin")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            userid = self.data.local.user.from_cardid(cardid)
            if userid is None:
                # Refuse to do anything
                print("No user for eacoin checkin request")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            valid = self.data.local.user.validate_pin(userid, pin)
            if not valid:
                # Refuse to do anything
                print("User entered invalid pin for eacoin checkin request")
                root.set_attribute('status', str(Status.INVALID_PIN))
                return root

            session = self.data.local.user.create_session(userid)

            if self.config['paseli']['infinite']:
                balance = PASELIHandler.INFINITE_PASELI_AMOUNT
            else:
                if self.config['machine']['arcade'] is None:
                    # There's no arcade for this machine, but infinite is not
                    # enabled, so there's no way to find a balance.
                    balance = 0
                else:
                    balance = self.data.local.user.get_balance(userid, self.config['machine']['arcade'])

            root.add_child(Node.s16('sequence', 0))
            root.add_child(Node.u8('acstatus', 0))
            root.add_child(Node.string('acid', 'DUMMY_ID'))
            root.add_child(Node.string('acname', 'DUMMY_NAME'))
            root.add_child(Node.s32('balance', balance))
            root.add_child(Node.string('sessid', session))
            return root

        if method == 'opcheckin':
            root = Node.void('eacoin')
            passwd = request.child_value('passwd')

            if passwd is None:
                # Refuse to return anything
                print("Invalid eacoin checkin request, missing passwd")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            if self.config['machine']['arcade'] is None:
                # Machine doesn't belong to an arcade
                print("Machine doesn't belong to an arcade")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            arcade = self.data.local.machine.get_arcade(self.config['machine']['arcade'])
            if arcade is None:
                # Refuse to do anything
                print("No arcade for operator checkin request")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            if arcade.pin != passwd:
                # Refuse to do anything
                print("User entered invalid pin for operator checkin request")
                root.set_attribute('status', str(Status.INVALID_PIN))
                return root

            session = self.data.local.machine.create_session(arcade.id)
            root.add_child(Node.string('sessid', session))
            return root

        elif method == 'consume':

            def make_resp(status: int, balance: int) -> Node:
                root = Node.void('eacoin')
                root.add_child(Node.u8('acstatus', status))
                root.add_child(Node.u8('autocharge', 0))
                root.add_child(Node.s32('balance', balance))
                return root

            session = request.child_value('sessid')
            payment = request.child_value('payment')
            service = request.child_value('service')
            details = request.child_value('detail')
            if session is None or payment is None:
                # Refuse to do anything
                print("Invalid eacoin consume request, missing sessid or payment")
                return make_resp(2, 0)

            userid = self.data.local.user.from_session(session)
            if userid is None:
                # Refuse to do anything
                print("Invalid session for eacoin consume request")
                return make_resp(2, 0)

            if self.config['paseli']['infinite']:
                balance = PASELIHandler.INFINITE_PASELI_AMOUNT - payment
            else:
                if self.config['machine']['arcade'] is None:
                    # There's no arcade for this machine, but infinite is not
                    # enabled, so there's no way to find a balance, assume failed
                    # consume payment.
                    balance = None
                else:
                    # Look up the new balance based on this delta. If there isn't enough,
                    # we will end up returning None here and exit without performing.
                    balance = self.data.local.user.update_balance(userid, self.config['machine']['arcade'], -payment)

                if balance is None:
                    print("Not enough balance for eacoin consume request")
                    return make_resp(1, self.data.local.user.get_balance(userid, self.config['machine']['arcade']))
                else:
                    self.data.local.network.put_event(
                        'paseli_transaction',
                        {
                            'delta': -payment,
                            'balance': balance,
                            'service': -service,
                            'reason': details,
                            'pcbid': self.config['machine']['pcbid'],
                        },
                        userid=userid,
                        arcadeid=self.config['machine']['arcade'],
                    )

            return make_resp(0, balance)

        elif method == 'getlog':
            root = Node.void('eacoin')
            sessid = request.child_value('sessid')
            logtype = request.child_value('logtype')
            target = request.child_value('target')
            limit = request.child_value('perpage')
            offset = request.child_value('offset')

            # Try to determine whether its a user or an arcade session
            userid = self.data.local.user.from_session(sessid)
            if userid is None:
                arcadeid = self.data.local.machine.from_session(sessid)
            else:
                arcadeid = None

            # Bail out if we don't have any idea what session this is
            if userid is None and arcadeid is None:
                print("Unable to determine session type")
                return root

            # If we're a user session, also look up the current arcade
            # so we display only entries that happened on this arcade.
            if userid is not None:
                arcade = self.data.local.machine.get_arcade(self.config['machine']['arcade'])
                if arcade is None:
                    print("Machine doesn't belong to an arcade")
                    return root
                arcadeid = arcade.id

            # Now, look up all transactions for this specific group
            events = self.data.local.network.get_events(
                userid=userid,
                arcadeid=arcadeid,
                event='paseli_transaction',
            )

            # Further filter it down to the current PCBID
            events = [event for event in events if event.data.get('pcbid') == target]

            # Grab the end of day today as a timestamp
            end_of_today = Time.end_of_today()
            time_format = '%Y-%m-%d %H:%M:%S'
            date_format = '%Y-%m-%d'

            # Set up common structure
            lognode = Node.void(logtype)
            topic = Node.void('topic')
            lognode.add_child(topic)
            summary = Node.void('summary')
            lognode.add_child(summary)

            # Display what day we are summed to
            topic.add_child(Node.string('sumdate', Time.format(Time.now(), date_format)))

            if logtype == 'last7days':
                # We show today in the today total, last 7 days prior in the week total
                beginning_of_today = end_of_today - Time.SECONDS_IN_DAY
                end_of_week = beginning_of_today
                beginning_of_week = end_of_week - Time.SECONDS_IN_WEEK

                topic.add_child(Node.string('sumfrom', Time.format(beginning_of_week, date_format)))
                topic.add_child(Node.string('sumto', Time.format(end_of_week, date_format)))
                today_total = sum([
                    -event.data.get_int('delta') for event in events
                    if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
                ])

                today_total = sum([
                    -event.data.get_int('delta') for event in events
                    if event.timestamp >= beginning_of_today and event.timestamp < end_of_today
                ])
                week_txns = [
                    -event.data.get_int('delta') for event in events
                    if event.timestamp >= beginning_of_week and event.timestamp < end_of_week
                ]
                week_total = sum(week_txns)
                if len(week_txns) > 0:
                    week_avg = int(sum(week_txns) / len(week_txns))
                else:
                    week_avg = 0

                # We display the totals for each day starting with yesterday and up through 7 days prior.
                # Index starts at 0 = yesterday, 1 = the day before, etc...
                items = []
                for days in range(0, 7):
                    end_of_day = end_of_week - (days * Time.SECONDS_IN_DAY)
                    start_of_day = end_of_day - Time.SECONDS_IN_DAY

                    items.append(sum([
                        -event.data.get_int('delta') for event in events
                        if event.timestamp >= start_of_day and event.timestamp < end_of_day
                    ]))

                topic.add_child(Node.s32('today', today_total))
                topic.add_child(Node.s32('average', week_avg))
                topic.add_child(Node.s32('total', week_total))
                summary.add_child(Node.s32_array('items', items))

            if logtype == 'last52weeks':
                # Start one week back, since the operator can look at last7days for newer stuff.
                beginning_of_today = end_of_today - Time.SECONDS_IN_DAY
                end_of_52_weeks = beginning_of_today - Time.SECONDS_IN_WEEK

                topic.add_child(Node.string('sumfrom', Time.format(end_of_52_weeks - (52 * Time.SECONDS_IN_WEEK), date_format)))
                topic.add_child(Node.string('sumto', Time.format(end_of_52_weeks, date_format)))

                # We index backwards, where index 0 = the first week back, 1 = the next week back after that, etc...
                items = []
                for weeks in range(0, 52):
                    end_of_range = end_of_52_weeks - (weeks * Time.SECONDS_IN_WEEK)
                    beginning_of_range = end_of_range - Time.SECONDS_IN_WEEK

                    items.append(sum([
                        -event.data.get_int('delta') for event in events
                        if event.timestamp >= beginning_of_range and event.timestamp < end_of_range
                    ]))

                summary.add_child(Node.s32_array('items', items))

            if logtype == 'eachday':
                start_ts = Time.now()
                end_ts = Time.now()
                weekdays = [0] * 7

                for event in events:
                    event_day = Time.days_into_week(event.timestamp)
                    weekdays[event_day] = weekdays[event_day] - event.data.get_int('delta')
                    if event.timestamp < start_ts:
                        start_ts = event.timestamp

                topic.add_child(Node.string('sumfrom', Time.format(start_ts, date_format)))
                topic.add_child(Node.string('sumto', Time.format(end_ts, date_format)))
                summary.add_child(Node.s32_array('items', weekdays))

            if logtype == 'eachhour':
                start_ts = Time.now()
                end_ts = Time.now()
                hours = [0] * 24

                for event in events:
                    event_hour = int((event.timestamp % Time.SECONDS_IN_DAY) / Time.SECONDS_IN_HOUR)
                    hours[event_hour] = hours[event_hour] - event.data.get_int('delta')
                    if event.timestamp < start_ts:
                        start_ts = event.timestamp

                topic.add_child(Node.string('sumfrom', Time.format(start_ts, date_format)))
                topic.add_child(Node.string('sumto', Time.format(end_ts, date_format)))
                summary.add_child(Node.s32_array('items', hours))

            if logtype == 'detail':
                history = Node.void('history')
                lognode.add_child(history)

                # Respect details paging
                if offset is not None:
                    events = events[offset:]
                if limit is not None:
                    events = events[:limit]

                # Output the details themselves
                for event in events:
                    card_no = ''
                    if event.userid is not None:
                        user = self.data.local.user.get_user(event.userid)
                        if user is not None:
                            cards = self.data.local.user.get_cards(user.id)
                            if len(cards) > 0:
                                card_no = CardCipher.encode(cards[0])

                    item = Node.void('item')
                    history.add_child(item)
                    item.add_child(Node.string('date', Time.format(event.timestamp, time_format)))
                    item.add_child(Node.s32('consume', -event.data.get_int('delta')))
                    item.add_child(Node.s32('service', -event.data.get_int('service')))
                    item.add_child(Node.string('cardtype', ''))
                    item.add_child(Node.string('cardno', ' ' * self.paseli_padding + card_no))
                    item.add_child(Node.string('title', ''))
                    item.add_child(Node.string('systemid', ''))

            if logtype == 'lastmonths':
                year, month, _ = Time.todays_date()
                this_month = Time.timestamp_from_date(year, month)
                last_month = Time.timestamp_from_date(year, month - 1)
                month_before = Time.timestamp_from_date(year, month - 2)

                topic.add_child(Node.string('sumfrom', Time.format(month_before, date_format)))
                topic.add_child(Node.string('sumto', Time.format(this_month, date_format)))

                for (start, end) in [(month_before, last_month), (last_month, this_month)]:
                    year, month, _ = Time.date_from_timestamp(start)

                    items = []
                    for day in range(0, 31):
                        begin_ts = start + (day * Time.SECONDS_IN_DAY)
                        end_ts = begin_ts + Time.SECONDS_IN_DAY
                        if begin_ts >= end:
                            # Passed the end of this month
                            items.append(0)
                        else:
                            # Sum up all the txns for this day
                            items.append(sum([
                                -event.data.get_int('delta') for event in events
                                if event.timestamp >= begin_ts and event.timestamp < end_ts
                            ]))

                    item = Node.void('item')
                    summary.add_child(item)
                    item.add_child(Node.s32('year', year))
                    item.add_child(Node.s32('month', month))
                    item.add_child(Node.s32_array('items', items))

            root.add_child(Node.u8('processing', 0))
            root.add_child(lognode)
            return root

        elif method == 'opchpass':
            root = Node.void('eacoin')
            oldpass = request.child_value('passwd')
            newpass = request.child_value('newpasswd')

            if oldpass is None or newpass is None:
                # Refuse to return anything
                print("Invalid eacoin pass change request, missing passwd")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            if self.config['machine']['arcade'] is None:
                # Machine doesn't belong to an arcade
                print("Machine doesn't belong to an arcade")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            arcade = self.data.local.machine.get_arcade(self.config['machine']['arcade'])
            if arcade is None:
                # Refuse to do anything
                print("No arcade for operator pass change request")
                root.set_attribute('status', str(Status.NO_PROFILE))
                return root

            if arcade.pin != oldpass:
                # Refuse to do anything
                print("User entered invalid pin for operator pass change request")
                root.set_attribute('status', str(Status.INVALID_PIN))
                return root

            arcade.pin = newpass
            self.data.local.machine.put_arcade(arcade)
            return root

        elif method == 'checkout':
            session = request.child_value('sessid')
            if session is not None:
                # Destroy the session so it can't be used for any other purchases
                self.data.local.user.destroy_session(session)

            root = Node.void('eacoin')
            return root

        elif method == 'opcheckout':
            session = request.child_value('sessid')
            if session is not None:
                # Destroy the session so it can't be used for any other purchases
                self.data.local.machine.destroy_session(session)

            root = Node.void('eacoin')
            return root

        # Invalid method
        return None
Example #18
0
def register() -> Response:
    card_number = request.form['card_number']
    pin = request.form['pin']
    username = request.form['username']
    email = request.form['email']
    password1 = request.form['password1']
    password2 = request.form['password2']

    # First, try to convert the card to a valid E004 ID
    try:
        cardid = CardCipher.decode(card_number)
    except CardCipherException:
        error('Invalid card number!')
        return register_display(card_number, username, email)

    # Now, see if this card ID exists already
    userid = g.data.local.user.from_cardid(cardid)
    if userid is None:
        error('This card has not been used on the network yet!')
        return register_display(card_number, username, email)

    # Now, make sure this user doesn't already have an account
    user = g.data.local.user.get_user(userid)
    if user.username is not None or user.email is not None:
        error('This card is already in use!')
        return register_display(card_number, username, email)

    # Now, see if the pin is correct
    if not g.data.local.user.validate_pin(userid, pin):
        error('The entered PIN does not match the PIN on the card!')
        return register_display(card_number, username, email)

    # Now, see if the username is valid
    if not valid_username(username):
        error('Invalid username!')
        return register_display(card_number, username, email)

    # Now, check whether the username is already in use
    if g.data.local.user.from_username(username) is not None:
        error('The chosen username is already in use!')
        return register_display(card_number, username, email)

    # Now, see if the email address is valid
    if not valid_email(email):
        error('Invalid email address!')
        return register_display(card_number, username, email)

    # Now, make sure that the passwords match
    if password1 != password2:
        error('Passwords do not match each other!')
        return register_display(card_number, username, email)

    # Now, make sure passwords are long enough
    if len(password1) < 6:
        error('Password is not long enough!')
        return register_display(card_number, username, email)

    # Now, create the account.
    user.username = username
    user.email = email
    g.data.local.user.put_user(user)
    g.data.local.user.update_password(userid, password1)

    # Now, log them into that created account!
    aes = AESCipher(g.config['secret_key'])
    sessionID = g.data.local.user.create_session(userid)
    success('Successfully registered account!')
    response = make_response(redirect(url_for('home_pages.viewhome')))
    response.set_cookie('SessionID', aes.encrypt(sessionID))
    return response
Example #19
0
 def __format_card(card: str) -> str:
     try:
         return CardCipher.encode(card)
     except CardCipherException:
         return '????????????????'