def basic_setup(self): self.user = UsersModel("test", "*****@*****.**", role=Roles.Admin) self.user.hash_password("test") self.user.save_to_db() self.user2 = UsersModel("test2", "*****@*****.**", role=Roles.User) self.user2.hash_password("test2") self.user2.save_to_db() self.book = BooksModel(1, 100, 1, "book1") self.book.save_to_db() self.book2 = BooksModel(2, 50, 13.1, "book2") self.book2.save_to_db() res = self.client.post("/api/login", data={ "email": self.user.email, "password": "******" }) self.token = json.loads(res.data)["token"] res = self.client.post("/api/login", data={ "email": self.user2.email, "password": "******" }) self.token2 = json.loads(res.data)["token"]
def admin_setup(self): password = "******" self.admin = UsersModel("admin", "*****@*****.**", Roles.Admin) self.admin.hash_password(password) self.admin.save_to_db() res = self.client.post("/api/login", data={"email": self.admin.email, "password": password}) self.token = json.loads(res.data)["token"]
def user_loader(username, password): print(username, password) Users = UsersModel() logged_user = Users.authenticate(username, password) if logged_user: return {'username': logged_user['name']} else: return None
def post(self): data = parse_user() check_constraints_user(data) with lock: user = UsersModel.find_by_username(data["username"]) if user: return { "message": f"An user with same username {data['username']} already exists" }, 409 user = UsersModel.find_by_email(data["email"]) if user: return { "message": f"An user with same email {data['email']} already exists" }, 409 password = data.pop("password") try: user = UsersModel(**data) user.hash_password(password) user.save_to_db() verify = VerifyModel(user.id) verify.save_to_db() verify.send_email(user.email, request.url_root) except Exception as e: return {"message": str(e)}, 500 return user.json(), 201
def basic_setup(self): password = "******" self.user = UsersModel("test", "test") self.user.hash_password(password) self.user.save_to_db() self.book = BooksModel(1, 1, 1, "test") self.book.save_to_db() res = self.client.post("/api/login", data={"email": self.user.email, "password": password}) self.token = json.loads(res.data)["token"]
def basic_setup(self): self.user = UsersModel("test123", "*****@*****.**") self.user.hash_password("Test1234") self.user.save_to_db() res = self.client.post("/api/login", data={ "email": self.user.email, "password": "******" }) self.token = json.loads(res.data)["token"]
def test_delete_but_keep(self): with self.app.app_context(): to_add = UsersModel('test', '*****@*****.**') to_add.hash_password('password') UsersModel.save_to_db(to_add) UsersModel.delete_from_db(UsersModel.find_by_username('test')) keeps = len( UsersModel.query.filter_by(username='******', state=False).all()) self.assertNotEqual(keeps, 0)
def post(self): data = parse_review() with lock: user = UsersModel.find_by_email(data['email']) check_user_and_book(user, data['isbn']) if data['score'] < 1 or data['score'] > 5: return { "message": f"{data['score']} is not a valid value for score. Score must be an integer ranging " f"from 1 to 5." }, 418 if ReviewsModel.find_by_isbn_user_id(data.isbn, user.id) is not None: return { "message": "Given user already posted a review. Did you meant to update it?" }, 403 data['user_id'] = user.id del data['email'] try: review = ReviewsModel(**data) review.save_to_db() except Exception as e: return {"message": str(e)}, 500 return review.json(), 201
def put(self, key): data = parse_data(True) del data["email"] check_constraints_user(data) with lock: recovery = PasswordRecoveryModel.find_by_key(key) if recovery is None: return { "message": f"Password Recovery with ['key':{key}] is invalid." }, 403 if recovery.has_time_expired(): return {"message": "Password Recovery time has expired."}, 403 user = UsersModel.find_by_id(recovery.user_id) if user is None or not user.state: return { "message": "User doesn't exist or has deleted the account." }, 404 try: user.update_password_from_db(data['new_password']) recovery.delete_from_db() except Exception as e: return {"message": str(e)}, 500 return {"user": user.json()}, 200
def save_transaction(cls, user_id, isbns, prices, quantities): transactions = [] email_trans = [] for isbn, price, quantity in zip(isbns, prices, quantities): book = BooksModel.find_by_isbn(isbn) cls.check_stock(book, quantity) transaction = TransactionsModel(user_id, isbn, price, quantity) transactions.append(transaction.json()) email_trans.append(transaction.email_text()) db.session.add(transaction) user = UsersModel.find_by_id(user_id) book_library = LibraryModel.find_by_id_and_isbn( user.id, transaction.isbn) if book_library: # if the book was already in library if book_library.library_type == LibraryType.WishList: # if it was in the wish list book_library.library_type = LibraryType.Bought # change it to bought book_library.state = State.Pending else: # if it wasnt in the library, enter it entry = LibraryModel(book.isbn, user.id, LibraryType.Bought, State.Pending) db.session.add(entry) cls.it_transaction += 1 db.session.commit() cls.send_email(user_id, email_trans) return transactions
def send_confirmation_mail(self): recipient = UsersModel.find_by_id(self.user_id).email quantity = str(self.quantity) isbn = str(self.isbn) subject = 'Order confirmation' message = 'Has comprat ' + quantity + ' llibre/s amb isbn ' + isbn send_email(recipient, subject, message)
def get(self, id_transaction): with lock: transaction = TransactionsModel.find_by_id(id_transaction) if not transaction: return {"message": f"Transaction with ['id_transaction':{id_transaction}] not found"}, 404 if UsersModel.find_by_id(transaction.user_id) != g.user: return {"message": "Invalid transaction, can only be yours"}, 401 return {"transaction": transaction.json()}, 200
def get(self, email): data = parse_reviews() with lock: user = UsersModel.find_by_email(email) if not user: return {"message": f"User with ['email':{email}] not found"}, 404 return {"user": user.json(**data)}, 200
def test_add(self): with self.app.app_context(): to_add = UsersModel('test', '*****@*****.**') to_add.hash_password('password') UsersModel.save_to_db(to_add) self.assertEqual( UsersModel.find_by_username('test').username, to_add.username)
def basic_setup(self): self.user = UsersModel("test", "*****@*****.**", role=Roles.Admin) self.user.hash_password("test") self.user.save_to_db() res = self.client.post("/api/login", data={ "email": self.user.email, "password": "******" }) self.token = json.loads(res.data)["token"] self.sinopsis = "For twelve thousand years the Galactic Empire has ruled supreme. Now it is dying. But only " \ "Hari Seldon, creator of the revolutionary science of psychohistory, can see into the future " \ "-- to a dark age of ignorance, barbarism, and warfare that will last thirty thousand years. " \ "To preserve knowledge and save mankind, Seldon gathers the best minds in the Empire -- both " \ "scientists and scholars -- and brings them to a bleak planet at the edge of the Galaxy to " \ "serve as a beacon of hope for a future generations. He calls his sanctuary the " \ "Foundation.\nBut soon the fledgling Foundation finds itself at the mercy of corrupt warlords " \ "rising in the wake of the receding Empire. Mankind's last best hope is faced with an " \ "agonizing choice: submit to the barbarians and be overrun -- or fight them and be destroyed. " self.isbn = 9780553803716 self.data_new = {"sinopsis": self.sinopsis, "precio": 8.60, "stock": 9} self.data_old = { "isbn": self.isbn, "stock": 10, "precio": 7.79, "titulo": "Foundation", "autor": "Isaac Asimov", "editorial": "Bantam Books", "url_imagen": "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1417900846l" "/29579.jpg", "fecha_de_publicacion": "2001-06-01" }
def json(self): """ Returns a dictionary with pairs of string of name of attribute and it's value. """ _ignore = self.isbn # Forces execution to parse properly the class, fixing the bug of transient data atr = self.__dict__.copy() user = UsersModel.find_by_id(self.user_id) atr['username'] = user.username if user.state else None del atr["_sa_instance_state"] return atr
def basic_setup(self): password = "******" self.user = UsersModel("test", "test") self.user.hash_password(password) self.user.save_to_db() self.book = BooksModel(1, 10, 10, "test") self.book.save_to_db() self.entry = LibraryModel(self.book.isbn, self.user.id, LibraryType.Bought) self.entry.save_to_db() res = self.client.post("api/login", data={ "email": self.user.email, "password": password }) self.token = json.loads(res.data)["token"]
def post(self, key): with lock: verify = VerifyModel.find_by_key(key) if verify is None: return {"message": f"Verify email with ['key':{key}] is invalid"}, 404 if verify.has_time_expired(): return {"message": f"Password Recovery time has expired."}, 403 user = UsersModel.find_by_id(verify.user_id) user.confirmed_email.confirmed_email = True return {"user": user.json()}, 200
def get(self, email): with lock: user = UsersModel.find_by_email(email) if user is None: return {"message": "User with ['email': " + email + "] Not Found"}, 404 if g.user != user: return {"message": "Invalid user, can only be yourself"}, 401 transactions = TransactionsModel.query.filter_by(user_id=user.id).all() grouped_transactions = TransactionsModel.group_transactions_by_id(transactions) return {'transactions': grouped_transactions}, 200
def check_user(email): user = UsersModel.find_by_email(email) if user is None: abort(404, message={"message": f"User with ['email': {email}] Not Found"}) if g.user != user: abort(401, message={ "message": "Invalid user to remove, can only be yourself" }) return user
def test_post_user_invalid_syntax(self): # Same checks will be done in the put of users with self.app.app_context(): # Username length less than 4 data = {"username": "******", "email": "*****@*****.**", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # email without @ data = {"username": "******", "email": "testemail.com", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # email without . data = {"username": "******", "email": "test@emailcom", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # email with invalid characters data = {"username": "******", "email": "test/()@email.com", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # email with ending to short data = {"username": "******", "email": "[email protected]", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # Password too short data = {"username": "******", "email": "test2@emailcom", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # Password without uppercase data = {"username": "******", "email": "test2@emailcom", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"])) # Password without numbers data = {"username": "******", "email": "test2@emailcom", "password": "******"} res = self.client.post("/api/user", data=data) self.assertEqual(400, res.status_code) self.assertIsNone(UsersModel.find_by_username(data["username"]))
def test_library_visibility_modification_other_user(self): with self.app.app_context(): self.basic_setup() user2 = UsersModel("test2", "test2") user2.hash_password("test2") user2.save_to_db() library = self.entry = LibraryModel(self.book.isbn, user2.id, LibraryType.Bought) library.save_to_db() res = self.client.delete( f"api/library/{user2.email}/visibility/{self.book.isbn}", headers={ "Authorization": 'Basic ' + base64.b64encode( (self.token + ":").encode('ascii')).decode('ascii') }) self.assertEqual(401, res.status_code) # Checks visibility doesn't change self.assertEqual( self.entry.visible, LibraryModel.find_by_id_and_isbn(self.user.id, self.book.isbn).visible)
def test_get_entry(self): with self.app.app_context(): user = UsersModel("test", "test") user.hash_password("test") user.save_to_db() book = BooksModel(1, 1, 1, "test") book.save_to_db() book2 = BooksModel(2, 1, 1, "test") book2.save_to_db() book3 = BooksModel(3, 1, 1, "test") book3.save_to_db() entry = LibraryModel(book.isbn, user.id, LibraryType.Bought, State.Pending) entry.save_to_db() entry2 = LibraryModel(book2.isbn, user.id, LibraryType.WishList, State.Pending) entry2.save_to_db() entry3 = LibraryModel(book3.isbn, user.id, LibraryType.Bought, State.Reading) entry3.save_to_db() res = self.client.post("api/login", data={"email": user.email, "password": "******"}) token = json.loads(res.data)["token"] res = self.client.get(f"api/userLibrary/{user.email}", headers={ "Authorization": 'Basic ' + base64.b64encode((token + ":").encode('ascii')).decode('ascii') }) self.assertEqual(200, res.status_code) expectedRes = list(map(lambda e: e.json(), [entry, entry3])) self.assertEqual(expectedRes, json.loads(res.data)["library"])
def test_get_all_transactions_no_admin(self): with self.app.app_context(): user = UsersModel("test", "*****@*****.**", role=Roles.User) user.hash_password("test") user.save_to_db() res = self.client.post("/api/login", data={ "email": user.email, "password": "******" }) token = json.loads(res.data)["token"] book = BooksModel(1, 1, 1, "book1") book.save_to_db() book2 = BooksModel(2, 2, 13.1, "book2") book2.save_to_db() isbns = [book.isbn, book2.isbn] prices = [book.precio, book2.precio] quantities = [1, 1] TransactionsModel.save_transaction(user.id, isbns, prices, quantities) res = self.client.get( "/api/allTransactions", headers={ "Authorization": 'Basic ' + base64.b64encode( (token + ":").encode('ascii')).decode('ascii') }) self.assertEqual(403, res.status_code)
def test_library_visibility_modification_other_user(self): with self.app.app_context(): self.basic_setup() user2 = UsersModel("test2", "test2") user2.hash_password("test2") user2.save_to_db() library = self.entry = LibraryModel(self.book.isbn, user2.id, LibraryType.Bought) library.save_to_db() new_data = { "state": State.Finished.name, "library_type": LibraryType.WishList.name } res = self.client.put( f"/api/library/{user2.email}/{self.book.isbn}", data=new_data, headers={ "Authorization": 'Basic ' + base64.b64encode( (self.token + ":").encode('ascii')).decode('ascii') }) self.assertEqual(401, res.status_code) self.assertEqual( self.entry.state, LibraryModel.find_by_id_and_isbn(self.user.id, self.book.isbn).state) self.assertEqual( self.entry.library_type, LibraryModel.find_by_id_and_isbn(self.user.id, self.book.isbn).library_type)
def test_post_recovery(self): with self.app.app_context(), mail.record_messages() as outbox: user = UsersModel("test", "*****@*****.**") user.hash_password("test") user.save_to_db() res = self.client.post(f"/api/recovery", data={"email": user.email}) self.assertEqual(201, res.status_code) self.assertEqual(1, len(outbox)) self.assertEqual(user.json(), json.loads(res.data)["user"])
def post(self): data = parse_user(False) with lock: account = UsersModel.find_by_email(data["email"]) if not account: return {"message": "Invalid email"}, 404 if not account.check_password(data["password"]): return {"message": "Invalid password"}, 400 token = account.generate_auth_token() return {'token': token.decode('ascii')}, 200
def test_post_entry_without_login(self): with self.app.app_context(): user = UsersModel("test", "test") user.hash_password("test2") user.save_to_db() res = self.client.post(f"api/library/{user.email}") self.assertEqual(401, res.status_code)
def test_put_recovery(self): with self.app.app_context(): user = UsersModel("test", "test") user.hash_password("test") user.save_to_db() recovery = PasswordRecoveryModel(user.id) recovery.save_to_db() new_password = "******" res = self.client.put(f"/api/recovery/{recovery.key}", data={"new_password": new_password}) self.assertEqual(200, res.status_code) self.assertEqual(user.json(), json.loads(res.data)["user"]) self.assertTrue(user.check_password(new_password))
def test_get_user(self): with self.app.app_context(): user = UsersModel("test", "*****@*****.**") user.hash_password("test") user.save_to_db() res = self.client.get("/api/user/[email protected]") self.assertEqual(200, res.status_code) self.assertEqual(user.json(), json.loads(res.data)["user"]) res = self.client.get("/api/user/doesntexist") self.assertEqual(404, res.status_code)