Example #1
0
def deleteUser(username):
    usMgr = UserManager()
    user = usMgr.getOne(username)
    if user is None:
        raise MissingKey("no user with this username exists")
    success = usMgr.deleteOne(username)
    return {"success": success}
Example #2
0
def register():
    usMgr = UserManager()
    newUserVal = request.json
    usrPK = usMgr.addOne(newUserVal)
    success = True if usrPK else False
    result = {"success": success}
    return result
 def setUp(self):
     logger = logging.getLogger(f"{__name__}.setUp")
     from app.UserManager import UserManager
     self.uMgr = UserManager()
     self.conn = self.uMgr.conn
     # clear table
     with self.conn.cursor() as cur:
         cur.execute(f"delete from {UserManager.TABLE_NAME}")
     self.conn.commit()
     # insert test user data
     self.uMgr.addOne(dict(zip(
         ["username", "password", "fName", "lName", "email"],
         ["stallylol", "123456", "Stally", "Duan", "*****@*****.**"]
     )))
     self.uMgr.addOne(dict(zip(
         ["username", "password", "fName", "lName", "email"],
         ["shiyugun", "abcdef", "Shiyu", "Gao", "*****@*****.**"]
     )))
     self.uMgr.addOne(dict(zip(
         ["username", "password", "fName", "lName", "email"],
         ["aspenrocks", "78910", "Aspen", "Forster", "*****@*****.**"]
     )))
     self.uMgr.addOne(dict(zip(
         ["username", "password", "fName", "lName", "email"],
         ["toBeDeleted", "wtfwtf", "Dummy", "Value", "*****@*****.**"]
     )))
     self.usernames = ["stallylol", "shiyugun", "aspenrocks", "toBeDeleted"]
Example #4
0
def findUser():
    usMgr = UserManager()
    query = usMgr.keepValidFieldsOnly(request.json, throw=True)
    # ignore empty values
    query = {
        k: v
        for k, v in query.items() if v is not None and v != "" and v != []
    }
    users = usMgr.getMany(query)
    return users
Example #5
0
def updateUser(username):
    usMgr = UserManager()
    newUserVal = usMgr.keepValidFieldsOnly(request.json, throw=True)
    # pop None / empty values
    newUserVal = {
        k: v
        for k, v in newUserVal.items() if v is not None and v != ""
    }
    success = usMgr.updateOne(username, newUserVal)
    result = {"success": success}
    return result
Example #6
0
def addUser():
    usMgr = UserManager()
    newUserVal = usMgr.keepValidFieldsOnly(request.json, throw=True)
    # pop None / empty values
    newUserVal = {
        k: v
        for k, v in newUserVal.items() if v is not None and v != ""
    }
    usrPk = usMgr.addOne(newUserVal)
    success = True if usrPk else False
    result = {"success": success}
    return result
Example #7
0
 def setUp(self):
     from app.BookingManager import BookingManager
     from app.UserManager import UserManager
     from app.CarManager import CarManager
     self.bkMgr = BookingManager()
     self.uMgr = UserManager()
     self.cMgr = CarManager()
     self.conn = self.bkMgr.conn
     self.bk_ids = [-1, -1, -1, -1, -1]
     self.car_ids = [-1] * 3
     self.usernames = []
     # firstly clear table
     with self.conn.cursor() as cur:
         cur.execute("delete from {}".format(BookingManager.TABLE_NAME))
         cur.execute("delete from {}".format(CarManager.TABLE_NAME))
         cur.execute("delete from {}".format(UserManager.TABLE_NAME))
     self.conn.commit()
     # insert test user data
     self._insertUsers()
     # insert test car data
     self._insertCars()
     # insert test booking data
     values = [[
         "stallylol", self.car_ids[0], '2020-05-01', '09:14:23',
         '2020-05-02', '09:15:00', "booked"
     ],
               [
                   "stallylol", self.car_ids[1], '2020-04-01', '09:14:23',
                   '2020-04-02', '09:15:00', "finished"
               ],
               [
                   "shiyugun", self.car_ids[2], '2020-04-23', '09:14:23',
                   '2020-04-25', '09:15:00', "cancelled"
               ],
               [
                   "shiyugun", self.car_ids[0], '2020-03-01', '05:20:00',
                   '2020-03-02', '06:15:00', "finished"
               ],
               [
                   'aspenrocks', self.car_ids[1], '2020-05-04', '11:14:23',
                   '2020-05-010', '12:15:00', "booked"
               ]]
     for i in range(5):
         self.bk_ids[i] = self.bkMgr.addOne(
             dict(
                 zip([
                     "username", "car_id", "date_booking", "time_booking",
                     "date_return", "time_return", "status"
                 ], values[i])))
class LoginManager:
    def __init__(self):
        self.user_manager = UserManager()

    def login_by_phone(self, phone=None):
        if not phone:
            return None

        user = self.user_manager.get_user_by_phone(phone)
        return user
class OrderManager:
    def __init__(self):
        self.user_manager = UserManager()

    def get_all_orders_for_collector(self, collector_id=None):
        if not collector_id:
            return None

        collector = self.user_manager.get_user_by_id(user_id=collector_id)

        if collector:
            orders_pickups = OrderPickup.objects.filter(collector=collector)
            return orders_pickups
        else:
            return None

    def get_order_by_id(self, order_id=None):
        if not order_id:
            return None

        if Order.objects.filter(id=order_id).exists():
            return Order.objects.get(id=order_id)
        else:
            return None

    def get_payable_by_order(self, order=None):
        if not order:
            return None

        transactions = Transaction.objects.filter(order=order)
        payable = order.total

        if transactions:
            payable = order.total - sum([txn.amt for txn in transactions])

        return payable
 def __init__(self):
     self.public_exponent = 65537
     self.key_size = 512
     self.user_manager = UserManager()
     self.otp_length = 4
class EncryptionManager:
    def __init__(self):
        self.public_exponent = 65537
        self.key_size = 512
        self.user_manager = UserManager()
        self.otp_length = 4

    def generate_key_pair_for_user(self, user_id):
        private_key = rsa.generate_private_key(
            public_exponent=self.public_exponent,
            key_size=self.key_size,
            backend=default_backend())
        public_key = private_key.public_key()

        user = self.user_manager.get_user_by_id(user_id=user_id)
        print(type(user))
        if user:
            user.privkey = private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()).decode()

            user.pubkey = public_key.public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo).decode(
                )

            user.save()

    def get_private_key_by_user_id(self, user_id):
        # user = self.user_manager.get_user_by_id(user_id=user_id)
        # if not user.privkey:
        #     self.generate_key_pair_for_user(user_id=user.id)
        #     user = self.user_manager.get_user_by_id(user_id=user_id)

        with open(settings.PRIVKEY, "rb") as key_file:
            private_key = serialization.load_pem_private_key(
                key_file.read(), password=None, backend=default_backend())

        return private_key

    def get_public_key_by_user_id(self, user_id):
        private_key = self.get_private_key_by_user_id(user_id)
        return private_key.public_key()

    def get_encrypted_cipher(self, user_id, data):
        public_key = self.get_public_key_by_user_id(user_id)
        ciphertext = public_key.encrypt(
            data.encode(),
            padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()),
                         algorithm=hashes.SHA1(),
                         label=None))
        return ciphertext

    def get_decrypt_cipher(self, user_id, ciphertext):
        private_key = self.get_private_key_by_user_id(user_id)
        plaintext = private_key.decrypt(
            ciphertext,
            padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA1()),
                         algorithm=hashes.SHA1(),
                         label=None))
        return plaintext

    def get_otp_string(self):
        otp = ""
        for _ in range(self.otp_length):
            otp += str(random.randint(1, 9))
        return otp

    def get_signature(self, data, user_id):
        private_key = self.get_private_key_by_user_id(user_id)
        signature = private_key.sign(
            data.encode(),
            padding.PSS(mgf=padding.MGF1(hashes.SHA1()),
                        salt_length=padding.PSS.MAX_LENGTH), hashes.SHA1())
        return signature

    def get_encoded_signature(self, signature):
        return b64encode(signature)

    def get_decoded_signature(self, signature):
        return b64decode(signature)

    def is_data_verified(self, data, signature, user_id):
        public_key = self.get_public_key_by_user_id(user_id)
        print(type(signature))
        try:
            public_key.verify(
                signature, data.encode(),
                padding.PSS(mgf=padding.MGF1(hashes.SHA1()),
                            salt_length=padding.PSS.MAX_LENGTH), hashes.SHA1())
            return True
        except Exception as e:
            print(e)
            return False
Example #12
0
class TestBookingManager(_ut.TestCase):
    def setUp(self):
        from app.BookingManager import BookingManager
        from app.UserManager import UserManager
        from app.CarManager import CarManager
        self.bkMgr = BookingManager()
        self.uMgr = UserManager()
        self.cMgr = CarManager()
        self.conn = self.bkMgr.conn
        self.bk_ids = [-1, -1, -1, -1, -1]
        self.car_ids = [-1] * 3
        self.usernames = []
        # firstly clear table
        with self.conn.cursor() as cur:
            cur.execute("delete from {}".format(BookingManager.TABLE_NAME))
            cur.execute("delete from {}".format(CarManager.TABLE_NAME))
            cur.execute("delete from {}".format(UserManager.TABLE_NAME))
        self.conn.commit()
        # insert test user data
        self._insertUsers()
        # insert test car data
        self._insertCars()
        # insert test booking data
        values = [[
            "stallylol", self.car_ids[0], '2020-05-01', '09:14:23',
            '2020-05-02', '09:15:00', "booked"
        ],
                  [
                      "stallylol", self.car_ids[1], '2020-04-01', '09:14:23',
                      '2020-04-02', '09:15:00', "finished"
                  ],
                  [
                      "shiyugun", self.car_ids[2], '2020-04-23', '09:14:23',
                      '2020-04-25', '09:15:00', "cancelled"
                  ],
                  [
                      "shiyugun", self.car_ids[0], '2020-03-01', '05:20:00',
                      '2020-03-02', '06:15:00', "finished"
                  ],
                  [
                      'aspenrocks', self.car_ids[1], '2020-05-04', '11:14:23',
                      '2020-05-010', '12:15:00', "booked"
                  ]]
        for i in range(5):
            self.bk_ids[i] = self.bkMgr.addOne(
                dict(
                    zip([
                        "username", "car_id", "date_booking", "time_booking",
                        "date_return", "time_return", "status"
                    ], values[i])))

    def _insertCars(self):
        self.car_ids[0] = self.cMgr.addOne(
            dict(
                zip([
                    "year", "car_model", "body_type", "num_seats",
                    "car_colour", "cost_hour", "car_status"
                ], [2020, "Honda", "sedan", 5, "yellow", 23.45, "available"])))
        self.car_ids[1] = self.cMgr.addOne(
            dict(
                zip([
                    "year", "car_model", "body_type", "num_seats",
                    "car_colour", "cost_hour", "latitude", "longitude",
                    "car_status"
                ], [
                    2019, "Hyundai", "sedan", 5, "blue", 36.99, -37.813629,
                    144.963058, "available"
                ])))
        self.car_ids[2] = self.cMgr.addOne(
            dict(
                zip([
                    "year", "car_model", "body_type", "num_seats",
                    "car_colour", "cost_hour", "latitude", "longitude",
                    "car_status"
                ], [
                    2016, "Jeep", "truck", 8, "Red", 54.99, -38.150002,
                    144.350006, "available"
                ])))

    def _insertUsers(self):
        self.usernames = ["stallylol", "shiyugun", "aspenrocks"]
        self.uMgr.addOne(
            dict(
                zip(["username", "password", "fName", "lName", "email"], [
                    "stallylol", "123456", "Stally", "Duan", "*****@*****.**"
                ])))
        self.uMgr.addOne(
            dict(
                zip(["username", "password", "fName", "lName", "email"],
                    ["shiyugun", "abcdef", "Shiyu", "Gao", "*****@*****.**"
                     ])))
        self.uMgr.addOne(
            dict(
                zip(["username", "password", "fName", "lName", "email"], [
                    "aspenrocks", "78910", "Aspen", "Forster",
                    "*****@*****.**"
                ])))

    def tearDown(self):
        # clear booking table
        with self.conn.cursor() as cur:
            for bk_id in self.bk_ids:
                cur.execute(
                    f"delete from {self.bkMgr.TABLE_NAME} where booking_id = %s",
                    bk_id)
            for car_id in self.car_ids:
                cur.execute(
                    f"delete from {self.cMgr.TABLE_NAME} where car_id = %s",
                    car_id)
            for username in self.usernames:
                cur.execute(
                    f"delete from {self.uMgr.TABLE_NAME} where username = %s",
                    username)
        self.conn.commit()

    def _countBookings(self):
        with self.conn.cursor() as cursor:
            cursor.execute("select count(*) from {}".format(
                self.bkMgr.TABLE_NAME))
            return cursor.fetchone()[0]

    def _bookingExists(self, booking_id):
        with self.conn.cursor() as cursor:
            cursor.execute(
                f"SELECT COUNT(*) FROM {self.bkMgr.TABLE_NAME} WHERE booking_id = %s",
                (booking_id, ))
            return cursor.fetchone()[0] == 1

    def testGetAll(self):
        log = logging.getLogger(f"{__name__}.testGetAll")
        # count total number of records
        count = self._countBookings()
        log.debug('number of booking records: ' + str(count))
        # confirm number of results from no arg call matches number of bookings
        self.assertEqual(count, len(self.bkMgr.getMany({})))

    def testGetAllForUser(self):
        # confirm that number of results returned matches number of specific users category
        self.assertEqual(2, len(self.bkMgr.getMany({"username": "******"})))
        self.assertEqual(1, len(self.bkMgr.getMany({"username":
                                                    "******"})))
        # confirm it returns zero entries when getting bookings for a non-existent user
        self.assertEqual(0, len(self.bkMgr.getMany({"username": "******"})))

    def testGetAllForUserFilterByStatu(self):
        # confirm returns correct result when supplied with user and status
        bookings = self.bkMgr.getMany({
            "username": "******",
            "status": "cancelled"
        })
        self.assertEqual(1, len(bookings))
        # confirm returns correct result when supplied with user and incorrect status keyword
        self.assertEqual(
            0,
            len(
                self.bkMgr.getMany({
                    "username": '******',
                    "status": 'somethingwrong'
                })))

    def testGetOne(self):
        '''check that `getOne` returns an item when supplying valid booking_id,
        and the returned item has the correct keys
        '''
        log = logging.getLogger(f"{__name__}.testGetOne")
        booking = self.bkMgr.getOne(self.bk_ids[0])
        self.assertTrue(self._bookingExists(self.bk_ids[0]))
        self.assertEqual(
            set([
                "booking_id", "username", "car_id", "date_booking",
                "time_booking", "date_return", "time_return", "status"
            ]), set(booking.keys()))

    def testGetOneNonExistent(self):
        '''confirm that `getOne` returns None when booking_id not in db'''
        nonExistentId = self.bk_ids[-1] + 10
        self.assertIsNone(self.bkMgr.getOne(nonExistentId))

    def testAddOne(self):
        count = self._countBookings()
        newBooking = dict(
            zip([
                "username", "car_id", "date_booking", "time_booking",
                "date_return", "time_return", "status"
            ], [
                "aspenrocks", self.car_ids[2], '2020-05-20', '10:00:00',
                '2020-05-25', '10:00:00', "booked"
            ]))
        bk_id = self.bkMgr.addOne(newBooking)
        self.bk_ids.append(bk_id)
        booking = self.bkMgr.getOne(bk_id)
        self.assertEqual(dict(**newBooking, booking_id=bk_id), booking)
        self.assertEqual(count + 1, self._countBookings())

    def testUpdateOneChangeStatus(self):
        # change status to 'finished'
        self.assertTrue(
            self.bkMgr.updateOne(self.bk_ids[0], {"status": "finished"}))
        self.assertTrue(
            self.bkMgr.updateOne(self.bk_ids[4], {"status": "cancelled"}))

    def testTransformDateTime(self):
        '''confirm that BookingManager.tranformDateTime transforms date & time from db format to ISO string
        '''
        booking = {
            "date_booking": date(2020, 1, 1),
            "time_booking": timedelta(hours=19)
        }
        result = self.bkMgr.tranformDateTime(booking)
        self.assertEqual(
            {
                "date_booking": "2020-01-01",
                "time_booking": "19:00:00"
            }, result)
class TestUserManager(_ut.TestCase):
    def setUp(self):
        logger = logging.getLogger(f"{__name__}.setUp")
        from app.UserManager import UserManager
        self.uMgr = UserManager()
        self.conn = self.uMgr.conn
        # clear table
        with self.conn.cursor() as cur:
            cur.execute(f"delete from {UserManager.TABLE_NAME}")
        self.conn.commit()
        # insert test user data
        self.uMgr.addOne(dict(zip(
            ["username", "password", "fName", "lName", "email"],
            ["stallylol", "123456", "Stally", "Duan", "*****@*****.**"]
        )))
        self.uMgr.addOne(dict(zip(
            ["username", "password", "fName", "lName", "email"],
            ["shiyugun", "abcdef", "Shiyu", "Gao", "*****@*****.**"]
        )))
        self.uMgr.addOne(dict(zip(
            ["username", "password", "fName", "lName", "email"],
            ["aspenrocks", "78910", "Aspen", "Forster", "*****@*****.**"]
        )))
        self.uMgr.addOne(dict(zip(
            ["username", "password", "fName", "lName", "email"],
            ["toBeDeleted", "wtfwtf", "Dummy", "Value", "*****@*****.**"]
        )))
        self.usernames = ["stallylol", "shiyugun", "aspenrocks", "toBeDeleted"]

    def tearDown(self):
        logger = logging.getLogger(f"{__name__}.tearDown")
        # delete all inserted test data
        with self.conn.cursor() as cur:
            for username in self.usernames:
                cur.execute(f"delete from {self.uMgr.TABLE_NAME} where username = %s", username)
        self.conn.commit()

    def _countUsers(self):
        with self.conn.cursor() as cursor:
            cursor.execute("SELECT count(*) from {}".format(self.uMgr.TABLE_NAME))
            return cursor.fetchone()[0]

    def _userExists(self, username):
        with self.connection.cursor() as cursor:
            cursor.execute(f"SELECT COUNT(*) FROM {self.uMgr.TABLE_NAME} WHERE username = %s", (username,))
            return cursor.fetchone()[0] == 1
    
    def testGetAll(self):
        '''confirm that number of records returned is same as number of 
        records in test_database
        '''
        self.assertEqual(self._countUsers(), len(self.uMgr.getMany({})))

    def testGetOne(self):
        # confirm true when user exists
        self.assertEqual('aspenrocks', self.uMgr.getOne('aspenrocks')["username"])
        # confirm that getItem() returns none when username not in db
        self.assertIsNone(self.uMgr.getOne("u34nonExistent"))

    def testAddOne(self):
        count = self._countUsers()
        success = self.uMgr.addOne(dict(zip(
            ["username", "password", 'fName', 'lName', "email"],
            ["papakase", "xxxyyy", "kaspian", "fitz", "*****@*****.**"]
        )))
        self.assertTrue(success)
        self.assertTrue(count + 1, self._countUsers())

    def testAddOneDuplicateUsername(self):
        '''confirm repeat username is rejected due to primary key constraint'''
        from app.errors.api_exceptions import DuplicateKey
        with self.assertRaises(DuplicateKey):
            self.uMgr.addOne(dict(zip(
                ["username", "password", 'fName', 'lName', "email"],
                ["stallylol", "612345", "Stally", "Duan", "*****@*****.**"]
            )))

    def testAddOneNullEmail(self):
        '''confirm null values are rejected due to not null constraint'''
        from app.errors.api_exceptions import InvalidArgument
        with self.assertRaises(InvalidArgument):
            self.uMgr.addOne(dict(zip(
                ["username", "password", 'fName', 'lName', "email"],
                ["papakase", "element", "kaspian", "fitz", None]
            )))

    def testUpdateOne(self):
        log = logging.getLogger(f"{__name__}.testUpdateOne")
        # update password
        log.debug(f"before updating, password is: {self.uMgr.getOne('stallylol')['password']}")
        self.assertTrue(self.uMgr.updateOne("stallylol", {"password": "******"}))
        self.assertEqual("111213", self.uMgr.getOne("stallylol")["password"])

    def testUpdateOneNonExistentUser(self):
        # fail update becuase username does not exist
        self.assertFalse(self.uMgr.updateOne("someoneelse", {"password": "******"}))
 def __init__(self):
     self.user_manager = UserManager()
Example #15
0
 def __init__(self):
     super().__init__()
     self.order_manager = OrderManager()
     self.encryption_manager = EncryptionManager()
     self.otp_manager = OTPManager()
     self.user_manager = UserManager()
Example #16
0
class OrdersView(View):
    def __init__(self):
        super().__init__()
        self.order_manager = OrderManager()
        self.encryption_manager = EncryptionManager()
        self.otp_manager = OTPManager()
        self.user_manager = UserManager()

    def get(self, request, order_id=None):
        login_id = request.session.get('login_id', None)

        if not login_id:
            redirect(reverse('home'))

        if not order_id:
            pickups = self.order_manager.get_all_orders_for_collector(login_id)
            context = {"pickups": pickups if pickups else []}
            return render(request, "orders.html", context)

        if order_id:
            order = self.order_manager.get_order_by_id(order_id=order_id)
            if order:
                payable = self.order_manager.get_payable_by_order(order)
                context = {"order": order, "payable": payable}
                return render(request, "order.html", context)
            else:
                return redirect(reverse('orders'))

    def post(self, request, order_id=None):
        login_id = request.session.get('login_id', None)

        if not login_id:
            redirect(reverse('home'))

        if order_id:
            if request.POST.get('action') == 'start_transaction':
                payable = request.POST.get('payable')
                if not payable:
                    return redirect(reverse('orders'))
                context = {
                    "payable": int(payable),
                    "order_id": order_id,
                    "user_id": login_id
                }
                return render(request, "transact.html", context)

            if request.POST.get('action') == 'start_verification':
                order_id = request.POST.get('order_id')
                payable = request.POST.get('payable')
                user_id = request.POST.get('user_id')

                if order_id and payable and user_id:
                    data = f"{order_id}.{payable}.{user_id}"

                    print(data)

                    ciphertext = self.encryption_manager.get_encrypted_cipher(
                        user_id=int(user_id), data=data)

                    plaintext = self.encryption_manager.get_decrypt_cipher(
                        user_id=user_id, ciphertext=ciphertext)

                    otp = self.encryption_manager.get_otp_string()

                    data = f"{plaintext.decode()}.{otp}"

                    signature = self.encryption_manager.get_signature(
                        data=data, user_id=user_id)
                    print(f'generated: {signature}')

                    otp_message = f"Your OTP is - {otp}. Payable amount is Rs.{payable}"
                    self.otp_manager.send_otp(
                        data=otp_message,
                        to=[self.user_manager.get_user_by_id(user_id).phone])
                    print(f'otp_message: {otp_message}')

                    context = {
                        "order_id": order_id,
                        "payable": payable,
                        "user_id": user_id,
                        "cipher": b64encode(ciphertext).decode(),
                        "signature": b64encode(signature).decode()
                    }
                    return render(request, "verify.html", context)
                else:
                    return redirect(reverse('orders'))

            if request.POST.get('action') == 'start_otp_validation':
                otp = request.POST.get('otp')
                order_id = request.POST.get('order_id')
                payable = request.POST.get('payable')
                user_id = request.POST.get('user_id')
                signature = request.POST.get('signature')
                print(f'Received: {b64decode(signature)}')

                data = f"{order_id}.{payable}.{user_id}.{otp}"

                is_verified = self.encryption_manager.is_data_verified(
                    data=data, signature=b64decode(signature), user_id=user_id)

                if is_verified:
                    return render(request, "success.html")

                else:
                    return redirect(reverse('orders'))