├── LICENSE ├── README.md ├── ch01 ├── main.py ├── readme.txt └── requirements.txt ├── ch02 ├── admin │ └── manager.py ├── audit_log.txt ├── background.py ├── feedback │ └── post.py ├── handler_exceptions.py ├── login │ └── user.py ├── main.py ├── places │ └── destination.py ├── readme.txt ├── request_log.txt ├── requirements.txt ├── tourist │ └── visit.py └── utility.py ├── ch03 ├── api │ ├── admin.py │ ├── admin_mcontainer.py │ ├── complaints.py │ ├── keywords.py │ ├── login.py │ ├── posts.py │ ├── recipes.py │ └── users.py ├── containers │ ├── multiple_containers.py │ └── single_container.py ├── dependencies │ ├── global_transactions.py │ ├── posts.py │ └── users.py ├── main.py ├── model │ ├── classifications.py │ ├── posts.py │ ├── recipes.py │ └── users.py ├── readme.txt ├── repository │ ├── admin.py │ ├── aggregates.py │ ├── complaints.py │ ├── factory.py │ ├── keywords.py │ ├── login.py │ ├── posts.py │ ├── recipes.py │ └── users.py ├── requirements.txt └── service │ ├── complaints.py │ ├── factory.py │ ├── posts.py │ ├── recipe_utilities.py │ └── recipes.py ├── ch04-faculty ├── configuration │ ├── config.py │ └── erp_settings.properties ├── controllers │ ├── admin.py │ ├── assignments.py │ └── books.py ├── main.py ├── models │ ├── data │ │ ├── faculty.py │ │ ├── facultydb.py │ │ └── library.py │ └── request │ │ ├── assignment.py │ │ ├── faculty.py │ │ └── library.py ├── readme.txt ├── repository │ ├── assignments.py │ ├── faculty.py │ ├── login.py │ └── signup.py └── services │ ├── assignments.py │ ├── faculty.py │ ├── login.py │ └── signup.py ├── ch04-library ├── configuration │ ├── config.py │ └── erp_settings.properties ├── controllers │ ├── admin.py │ └── management.py ├── main.py ├── models │ ├── data │ │ ├── library.py │ │ └── librarydb.py │ └── request │ │ └── library.py ├── readme.txt ├── repository │ ├── books.py │ ├── issuance.py │ └── reservations.py └── services │ ├── books.py │ ├── issuance.py │ └── reservations.py ├── ch04-student ├── configuration │ ├── config.py │ └── erp_settings.properties ├── controllers │ ├── admin.py │ ├── assignments.py │ └── reservations.py ├── main.py ├── models │ ├── data │ │ ├── library.py │ │ ├── students.py │ │ └── studentsdb.py │ └── request │ │ ├── assignment.py │ │ ├── library.py │ │ └── students.py ├── readme.txt ├── repository │ ├── login.py │ ├── signup.py │ └── students.py └── services │ ├── login.py │ ├── signup.py │ └── students.py ├── ch04 ├── configuration │ ├── config.py │ └── erp_settings.properties ├── controller │ └── university.py ├── faculty_mgt │ ├── controllers │ │ ├── admin.py │ │ ├── assignments.py │ │ └── books.py │ ├── faculty_main.py │ ├── models │ │ ├── data │ │ │ ├── faculty.py │ │ │ └── facultydb.py │ │ └── request │ │ │ ├── assignment.py │ │ │ ├── faculty.py │ │ │ └── library.py │ ├── repository │ │ ├── assignments.py │ │ ├── faculty.py │ │ ├── login.py │ │ └── signup.py │ └── services │ │ ├── assignments.py │ │ ├── faculty.py │ │ ├── login.py │ │ └── signup.py ├── gateway │ └── api_router.py ├── info.log ├── library_mgt │ ├── controllers │ │ ├── admin.py │ │ └── management.py │ ├── library_main.py │ ├── models │ │ ├── data │ │ │ ├── library.py │ │ │ └── librarydb.py │ │ └── request │ │ │ └── library.py │ ├── repository │ │ ├── books.py │ │ ├── issuance.py │ │ └── reservations.py │ └── services │ │ ├── books.py │ │ ├── issuance.py │ │ └── reservations.py ├── main.py ├── readme.txt ├── requirements.txt └── student_mgt │ ├── controllers │ ├── admin.py │ ├── assignments.py │ └── reservations.py │ ├── models │ ├── data │ │ ├── students.py │ │ └── studentsdb.py │ └── request │ │ ├── assignment.py │ │ ├── library.py │ │ └── students.py │ ├── repository │ ├── login.py │ ├── signup.py │ └── students.py │ ├── services │ ├── login.py │ ├── signup.py │ └── students.py │ └── student_main.py ├── ch05a ├── api │ ├── admin.py │ ├── login.py │ ├── members.py │ └── trainers.py ├── cqrs │ ├── commands.py │ ├── handlers.py │ ├── queries.py │ └── trainers │ │ ├── command │ │ ├── create_handlers.py │ │ ├── delete_handlers.py │ │ └── update_handlers.py │ │ └── query │ │ └── query_handlers.py ├── database │ ├── fcms-erd.png │ └── fcms.sql ├── db_config │ ├── gino_connect.py │ ├── pony_connect.py │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ ├── gino_models.py │ │ ├── pony_models.py │ │ └── sqlalchemy_models.py │ └── requests │ │ ├── attendance.py │ │ ├── login.py │ │ ├── members.py │ │ ├── signup.py │ │ └── trainers.py ├── readme.txt ├── repository │ ├── gino │ │ └── trainers.py │ ├── pony │ │ └── members.py │ └── sqlalchemy │ │ ├── login.py │ │ └── signup.py └── requirements.txt ├── ch05b ├── api │ ├── attendance.py │ ├── gym.py │ └── login.py ├── database │ └── fcms-erd.png ├── db_config │ ├── peewee_connect.py │ └── sqlalchemy_async_connect.py ├── main.py ├── models │ ├── data │ │ ├── peewee_models.py │ │ └── sqlalchemy_async_models.py │ └── requests │ │ ├── attendance.py │ │ ├── gym.py │ │ └── login.py ├── readme.txt ├── repository │ ├── peewee │ │ └── login.py │ └── sqlalchemy │ │ ├── attendance.py │ │ └── gym.py └── requirements.txt ├── ch06 ├── api │ ├── book.py │ ├── buyer.py │ ├── buyer_async.py │ ├── cart.py │ ├── login.py │ ├── order.py │ ├── profile.py │ ├── purchase.py │ ├── receipt.py │ └── reference.py ├── database │ ├── UML design.png │ └── obrs_db.zip ├── db_config │ ├── beanie_config.py │ ├── mongoengine_config.py │ ├── mongoframe_config.py │ ├── motor_config.py │ ├── odmantic_config.py │ └── pymongo_config.py ├── main.py ├── models │ ├── data │ │ ├── beanie.py │ │ ├── mongoengine.py │ │ ├── mongoframe.py │ │ ├── odmantic.py │ │ └── pymongo.py │ └── request │ │ ├── buyer.py │ │ ├── category.py │ │ ├── login.py │ │ ├── order.py │ │ ├── profile.py │ │ └── purchase.py ├── readme.txt ├── repository │ ├── beanie │ │ ├── cart.py │ │ ├── order.py │ │ └── receipt.py │ ├── mongoengine │ │ ├── book.py │ │ ├── login.py │ │ └── profile.py │ ├── mongoframe │ │ ├── book.py │ │ └── reference.py │ ├── motor │ │ └── buyer.py │ ├── odmantic │ │ └── purchase.py │ └── pymongo │ │ └── buyer.py └── requirements.txt ├── ch07a ├── api │ ├── admin.py │ ├── auction.py │ ├── bid.py │ ├── login.py │ └── profile.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── auctions.py │ │ ├── bids.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── auctions.py │ ├── bids.py │ ├── login.py │ ├── profile.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07b ├── api │ ├── admin.py │ ├── auction.py │ ├── bid.py │ ├── login.py │ └── profile.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── generate_hash.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── auctions.py │ │ ├── bids.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── auctions.py │ ├── bids.py │ ├── login.py │ ├── profile.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07c ├── api │ ├── admin.py │ ├── auction.py │ ├── bid.py │ ├── login.py │ └── profile.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── auctions.py │ │ ├── bids.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── auctions.py │ ├── bids.py │ ├── login.py │ ├── profile.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07d ├── api │ ├── admin.py │ ├── auction.py │ ├── bid.py │ ├── login.py │ └── profile.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── auctions.py │ │ ├── bids.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── auctions.py │ ├── bids.py │ ├── login.py │ ├── profile.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07e ├── api │ ├── admin.py │ ├── auction.py │ ├── bid.py │ ├── login.py │ └── profile.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── auctions.py │ │ ├── bids.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── auctions.py │ ├── bids.py │ ├── login.py │ ├── permission.py │ ├── profile.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07f ├── api │ ├── admin.py │ ├── auction.py │ ├── bid.py │ ├── login.py │ └── profile.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── auctions.py │ │ ├── bids.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── auctions.py │ ├── bids.py │ ├── login.py │ ├── permission.py │ ├── profile.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07g ├── api │ ├── admin.py │ └── login.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── login.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── login.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07h ├── api │ ├── admin.py │ └── login.py ├── app.env ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── login.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── login.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07i ├── api │ ├── admin.py │ └── login.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── login.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── login.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch07j ├── api │ ├── admin.py │ └── login.py ├── database │ └── soas.sql ├── db_config │ └── sqlalchemy_connect.py ├── main.py ├── models │ ├── data │ │ └── sqlalchemy_models.py │ └── request │ │ ├── login.py │ │ ├── signup.py │ │ └── tokens.py ├── readme.txt ├── repository │ ├── login.py │ ├── permission.py │ └── signup.py ├── requirements.txt └── security │ └── secure.py ├── ch08 ├── api │ ├── admin.py │ ├── billing.py │ ├── content.py │ ├── customer.py │ ├── login.py │ ├── messenger.py │ ├── publication.py │ ├── sales.py │ ├── subscription.py │ └── vendor.py ├── celery_test.py ├── cert.pem ├── config │ └── db │ │ └── gino_db.py ├── data │ └── billing-2022-03-16.csv ├── database │ └── nsms.sql ├── key.pem ├── main.py ├── models │ ├── data │ │ └── nsms.py │ └── request │ │ ├── admin.py │ │ ├── billing.py │ │ ├── content.py │ │ ├── customer.py │ │ ├── login.py │ │ ├── messenger.py │ │ ├── publication.py │ │ ├── sales.py │ │ ├── subscription.py │ │ └── vendor.py ├── readme.txt ├── repository │ ├── admin.py │ ├── billing.py │ ├── content.py │ ├── customer.py │ ├── login.py │ ├── messenger.py │ ├── publication.py │ ├── sales.py │ ├── subscription.py │ └── vendor.py ├── requirements.txt └── services │ ├── admin.py │ ├── billing.py │ ├── login.py │ ├── sales.py │ └── subscription.py ├── ch09 ├── api │ ├── keyword.py │ ├── login.py │ ├── question.py │ ├── restaurant.py │ ├── route_decrypt.py │ ├── route_extract.py │ └── route_transform.py ├── config │ └── db.py ├── database │ └── orrs_db.zip ├── files │ ├── file.txt │ ├── logo.jpg │ ├── questions.txt │ └── sample.mp4 ├── main.py ├── models │ ├── data │ │ ├── orrs.py │ │ └── ratings_enum.py │ ├── documentation │ │ ├── __pycache__ │ │ │ └── response.cpython-38.pyc │ │ └── response.py │ └── request │ │ ├── ambiance_rate.py │ │ ├── feedback.py │ │ ├── food_rate.py │ │ ├── keyword.py │ │ ├── login.py │ │ ├── profile.py │ │ ├── question.py │ │ ├── restaurant.py │ │ └── secured_messages.py ├── readme.txt ├── repository │ ├── keyword.py │ ├── login.py │ ├── question.py │ ├── restaurant.py │ └── session.py ├── requirements.txt ├── static │ ├── css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ └── js │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ └── jquery-3.6.0.js ├── templates │ ├── layout.html │ ├── page.html │ ├── upload_file.html │ └── users.html ├── test │ ├── __init__.py │ ├── test_login.py │ ├── test_restaurants.py │ └── test_route_extract.py └── util │ ├── auth_session.py │ ├── custom_request.py │ ├── custom_routes.py │ └── json_date.py ├── ch10-mongo ├── api │ ├── officer.py │ ├── survey_graphene_login.py │ ├── survey_graphene_profile.py │ ├── survey_neo4j.py │ └── survey_workflow.py ├── config │ ├── pccs.py │ └── pcss_neo4j.py ├── database │ └── pccs_db.zip ├── files │ ├── survey.csv │ └── survey.xlsx ├── main.py ├── models │ ├── data │ │ ├── __pycache__ │ │ │ ├── pccs.cpython-38.pyc │ │ │ ├── pccs_beanie.cpython-38.pyc │ │ │ └── pccs_graphql.cpython-38.pyc │ │ ├── pccs_beanie.py │ │ └── pccs_graphql.py │ └── request │ │ ├── __pycache__ │ │ ├── pccs_general.cpython-38.pyc │ │ ├── pccs_neo4j.cpython-38.pyc │ │ └── surveyor.cpython-38.pyc │ │ ├── pccs_general.py │ │ └── pccs_neo4j.py ├── readme.txt ├── repository │ ├── choices.py │ ├── login.py │ ├── profile.py │ ├── question.py │ └── respondent.py ├── requirements.txt └── services │ └── tasks.py ├── ch10-relational ├── README.md ├── app.py ├── conftest.py ├── countries.csv ├── data.json ├── files │ ├── sample.csv │ └── survey_data.csv ├── main.py ├── piccolo_conf.py ├── piccolo_conf_test.py ├── requirements.txt ├── static │ ├── favicon.ico │ └── main.css ├── survey │ ├── __init__.py │ ├── api │ │ ├── answer.py │ │ ├── choices.py │ │ ├── data_analysis.py │ │ ├── data_files.py │ │ ├── data_plots.py │ │ ├── data_stats.py │ │ ├── education.py │ │ ├── graphql.py │ │ ├── location.py │ │ ├── login.py │ │ ├── mynumpy.py │ │ ├── occupation.py │ │ ├── profile.py │ │ ├── question.py │ │ └── respondent.py │ ├── models.py │ ├── piccolo_app.py │ ├── piccolo_migrations │ │ ├── 2022-06-09T18-08-51-592478.py │ │ ├── 2022-06-09T19-26-00-511909.py │ │ └── __init__.py │ ├── repository │ │ ├── answers.py │ │ ├── choices.py │ │ ├── education.py │ │ ├── location.py │ │ ├── login.py │ │ ├── occupation.py │ │ ├── profile.py │ │ ├── questions.py │ │ └── respondent.py │ └── tables.py └── templates │ ├── render_survey.html │ └── upload_survey.html ├── ch11-app-decompose ├── Dockerfile ├── ch11 │ ├── api │ │ ├── login.py │ │ ├── officials.py │ │ └── players.py │ ├── ch11_django │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── ch11_flask │ │ ├── api │ │ │ ├── __init__.py │ │ │ └── schedule.py │ │ └── app.py │ ├── config │ │ └── db.py │ ├── db.sqlite3 │ ├── main.py │ ├── manage.py │ ├── models │ │ └── data.py │ ├── readme.txt │ ├── repository │ │ ├── login.py │ │ ├── officials.py │ │ └── players.py │ ├── requirements.txt │ └── sports │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ └── views.py ├── docker-compose.yaml ├── readme.txt └── requirements.txt ├── ch11-app-proxy ├── Dockerfile ├── nginx_config.conf └── readme.txt ├── ch11-app ├── Dockerfile ├── ch11 │ ├── api │ │ ├── login.py │ │ ├── officials.py │ │ └── players.py │ ├── ch11_django │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── ch11_flask │ │ ├── api │ │ │ ├── __init__.py │ │ │ └── schedule.py │ │ └── app.py │ ├── config │ │ └── db.py │ ├── db.sqlite3 │ ├── main.py │ ├── manage.py │ ├── models │ │ └── data.py │ ├── readme.txt │ ├── repository │ │ ├── login.py │ │ ├── officials.py │ │ └── players.py │ ├── requirements.txt │ └── sports │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ └── views.py ├── readme.txt └── requirements.txt ├── ch11-ws-eureka └── ch11-eureka-server │ ├── HELP.md │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ ├── src │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── packt │ │ │ │ └── chapter11 │ │ │ │ └── registry │ │ │ │ └── ServerRegistryApplication.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ └── ServerRegistryApplicationTests.java │ └── target │ └── classes │ ├── META-INF │ ├── MANIFEST.MF │ └── maven │ │ └── com.example │ │ └── demo │ │ ├── pom.properties │ │ └── pom.xml │ ├── application.properties │ └── org │ └── packt │ └── chapter11 │ └── registry │ └── ServerRegistryApplication.class ├── ch11 ├── api │ ├── login.py │ ├── officials.py │ └── players.py ├── ch11_django │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── ch11_flask │ ├── api │ │ ├── __init__.py │ │ └── schedule.py │ └── app.py ├── config │ └── db.py ├── db.sqlite3 ├── main.py ├── manage.py ├── models │ └── data.py ├── readme.txt ├── repository │ ├── login.py │ ├── officials.py │ └── players.py ├── requirements.txt └── sports │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py └── database └── osms_db.zip /ch01/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Online Academic Discussion Forum 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: July 30, 2021 6 | 7 | =========================== Description ==================================== 8 | 9 | This application must provide online support for knowledge construction and communication 10 | mechanism among students, faculty, family members, or users in an organization. 11 | It is a microservice application that can establish an exchange of ideas and discuss 12 | unlimited topics, including social activities and educational ideas among users. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | No database included yet. 16 | 17 | The requirements.txt will guide you with the dependencies. Just install by running: 18 | pip install -r requirements.txt 19 | -------------------------------------------------------------------------------- /ch01/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | bcrypt==3.2.2 3 | cffi==1.15.0 4 | click==8.1.3 5 | colorama==0.4.5 6 | fastapi==0.78.0 7 | h11==0.13.0 8 | idna==3.3 9 | pycparser==2.21 10 | pydantic==1.9.1 11 | python-multipart==0.0.5 12 | six==1.16.0 13 | sniffio==1.2.0 14 | starlette==0.19.1 15 | typing_extensions==4.2.0 16 | uvicorn==0.18.2 17 | -------------------------------------------------------------------------------- /ch02/audit_log.txt: -------------------------------------------------------------------------------- 1 | tourist 0d5d1cd4-0979-11ec-b5c4-b4d5bd98aef8 executed login at 2021-08-30 18:00:39.445809tourist 16009511-0984-11ec-a3bf-b4d5bd98aef8 executed login at 2021-08-30 19:19:28.316680tourist 94458494-0986-11ec-86c1-b4d5bd98aef8 executed login at 2021-08-30 19:37:30.267336 -------------------------------------------------------------------------------- /ch02/background.py: -------------------------------------------------------------------------------- 1 | 2 | from datetime import datetime 3 | 4 | def audit_log_transaction(touristId: str, message=""): 5 | with open("audit_log.txt", mode="a") as logfile: 6 | content = f"tourist {touristId} executed {message} at {datetime.now()}" 7 | logfile.write(content) 8 | 9 | 10 | -------------------------------------------------------------------------------- /ch02/handler_exceptions.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import HTTPException 3 | 4 | class PostFeedbackException(HTTPException): 5 | def __init__(self, detail: str, status_code: int): 6 | self.status_code = status_code 7 | self.detail = detail 8 | 9 | class PostRatingException(HTTPException): 10 | def __init__(self, detail: str, status_code: int): 11 | self.status_code = status_code 12 | self.detail = detail 13 | 14 | 15 | -------------------------------------------------------------------------------- /ch02/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | fastapi==0.78.0 5 | h11==0.13.0 6 | idna==3.3 7 | pydantic==1.9.1 8 | python-multipart==0.0.5 9 | six==1.16.0 10 | sniffio==1.2.0 11 | starlette==0.19.1 12 | typing_extensions==4.2.0 13 | uvicorn==0.18.2 14 | -------------------------------------------------------------------------------- /ch02/utility.py: -------------------------------------------------------------------------------- 1 | async def check_post_owner(feedbacks, fid, touristId): 2 | return feedbacks[fid].tourist_id == touristId -------------------------------------------------------------------------------- /ch03/api/admin.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends 2 | from fastapi.encoders import jsonable_encoder 3 | 4 | import sys 5 | from dependency_injector.wiring import inject, Provide 6 | 7 | from repository.admin import AdminRepository 8 | from containers.single_container import Container 9 | 10 | 11 | router = APIRouter() 12 | 13 | @router.get("/admin/login/details/list") 14 | @inject 15 | def list_login_details(adminservice: AdminRepository = Depends(Provide[Container.adminservice])): 16 | login_details_json = jsonable_encoder(adminservice.query_login_details()) 17 | return login_details_json 18 | 19 | 20 | @router.get("/admin/user/profiles/list") 21 | @inject 22 | def list_user_profiles(adminservice: AdminRepository = Depends(Provide[Container.adminservice])): 23 | user_profiles_json = jsonable_encoder(adminservice.query_user_profiles()) 24 | return user_profiles_json 25 | 26 | container = Container() 27 | container.wire(modules=[sys.modules[__name__]]) 28 | 29 | -------------------------------------------------------------------------------- /ch03/api/admin_mcontainer.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends 2 | from fastapi.encoders import jsonable_encoder 3 | 4 | import sys 5 | from dependency_injector.wiring import inject, Provide 6 | 7 | from repository.admin import AdminRepository 8 | from containers.multiple_containers import RecipeAppContainer 9 | 10 | router = APIRouter() 11 | 12 | @router.get("/admin/logs/visitors/list") 13 | @inject 14 | def list_logs_visitors(adminservice: AdminRepository = Depends(Provide[RecipeAppContainer.admincontainer.adminservice])): 15 | logs_visitors_json = jsonable_encoder(adminservice.query_logs_visitor()) 16 | return logs_visitors_json 17 | 18 | container = RecipeAppContainer() 19 | container.wire(modules=[sys.modules[__name__]]) -------------------------------------------------------------------------------- /ch03/api/posts.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends 2 | from fastapi.encoders import jsonable_encoder 3 | 4 | from dependencies.posts import check_feedback_length 5 | from model.classifications import RecipeRating 6 | from model.posts import Post 7 | from service.factory import get_post_service 8 | from uuid import UUID 9 | from datetime import date 10 | 11 | router = APIRouter() 12 | 13 | async def create_post(id:UUID, feedback: str, rating: RecipeRating, userId: UUID, date_posted: date): 14 | post = {"id": id, "feedback": feedback, "rating": rating, "userId" : userId, "date_posted": date_posted} 15 | return post 16 | 17 | @router.post("/posts/insert", dependencies=[Depends(check_feedback_length)]) 18 | async def insert_post_feedback(post=Depends(create_post), handler=Depends(get_post_service)): 19 | print('hello') 20 | post_dict = jsonable_encoder(post) 21 | 22 | post_obj = Post(**post_dict) 23 | 24 | handler.add_post(post_obj) 25 | return post 26 | 27 | -------------------------------------------------------------------------------- /ch03/containers/multiple_containers.py: -------------------------------------------------------------------------------- 1 | 2 | from dependency_injector import containers, providers 3 | 4 | from repository.login import LoginRepository 5 | from repository.admin import AdminRepository 6 | from repository.keywords import KeywordRepository 7 | 8 | class KeywordsContainer(containers.DeclarativeContainer): 9 | keywordservice = providers.Factory(KeywordRepository) 10 | 11 | class AdminContainer(containers.DeclarativeContainer): 12 | adminservice = providers.Singleton(AdminRepository) 13 | 14 | class LoginContainer(containers.DeclarativeContainer): 15 | loginservice = providers.Factory(LoginRepository) 16 | 17 | class RecipeAppContainer(containers.DeclarativeContainer): 18 | keywordcontainer = providers.Container(KeywordsContainer) 19 | admincontainer = providers.Container(AdminContainer) 20 | logincontainer = providers.Container(LoginContainer) -------------------------------------------------------------------------------- /ch03/containers/single_container.py: -------------------------------------------------------------------------------- 1 | from dependency_injector import containers, providers 2 | 3 | from repository.users import login_details 4 | from repository.login import LoginRepository 5 | from repository.admin import AdminRepository 6 | from repository.keywords import KeywordRepository 7 | from service.recipe_utilities import get_recipe_names 8 | 9 | class Container(containers.DeclarativeContainer): 10 | loginservice = providers.Factory(LoginRepository) 11 | adminservice = providers.Singleton(AdminRepository) 12 | keywordservice = providers.Factory(KeywordRepository) 13 | recipe_util = providers.Callable(get_recipe_names) 14 | login_repo = providers.Dict(login_details) 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch03/dependencies/global_transactions.py: -------------------------------------------------------------------------------- 1 | from fastapi import Request 2 | from uuid import uuid1 3 | 4 | service_paths_log = dict() 5 | 6 | def log_transaction(request: Request): 7 | service_paths_log[uuid1()] = request.url.path -------------------------------------------------------------------------------- /ch03/dependencies/posts.py: -------------------------------------------------------------------------------- 1 | from fastapi import Request, HTTPException 2 | 3 | def check_feedback_length(request: Request): 4 | feedback = request.query_params["feedback"] 5 | if len(feedback) < 20: 6 | raise HTTPException(status_code=403, detail="length of feedback should not be lower than 20") -------------------------------------------------------------------------------- /ch03/dependencies/users.py: -------------------------------------------------------------------------------- 1 | from fastapi import Request, HTTPException 2 | from repository.aggregates import stats_user_type 3 | import json 4 | 5 | def count_user_by_type(request: Request): 6 | try: 7 | count = stats_user_type[request.query_params.get("type")] 8 | count += 1 9 | stats_user_type[request.query_params.get("type")] = count 10 | print(json.dumps(stats_user_type)) 11 | except: 12 | stats_user_type[request.query_params.get("type")] = 1 13 | 14 | def check_credential_error(request: Request): 15 | try: 16 | username = request.query_params.get("username") 17 | password = request.query_params.get("password") 18 | if username == password: 19 | raise HTTPException(status_code=403, detail="username should not be equal to password") 20 | except: 21 | raise HTTPException(status_code=500, detail="encountered internal problems") -------------------------------------------------------------------------------- /ch03/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, Depends 2 | 3 | from api import recipes, users, posts, login, admin, keywords, admin_mcontainer, complaints 4 | from dependencies.global_transactions import log_transaction 5 | 6 | app = FastAPI(dependencies=[Depends(log_transaction)]) 7 | 8 | app.include_router(recipes.router, prefix="/ch03") 9 | app.include_router(users.router, prefix="/ch03") 10 | app.include_router(posts.router, prefix="/ch03") 11 | app.include_router(login.router, prefix="/ch03") 12 | app.include_router(admin.router, prefix="/ch03") 13 | app.include_router(keywords.router, prefix="/ch03") 14 | app.include_router(admin_mcontainer.router, prefix="/ch03") 15 | app.include_router(complaints.router, prefix="/ch03") 16 | 17 | @app.get("/ch03") 18 | def index(): 19 | return {"message": "Cooking Recipe Rating Prototype!"} -------------------------------------------------------------------------------- /ch03/model/posts.py: -------------------------------------------------------------------------------- 1 | from uuid import UUID 2 | from datetime import date 3 | from model.classifications import RecipeRating 4 | 5 | 6 | class Post: 7 | def __init__(self, id: UUID, feedback: str, rating: RecipeRating, userId: UUID, date_posted: date): 8 | self.id = id 9 | self.feedback = feedback 10 | self.rating = rating 11 | self.userId = userId 12 | self.date_posted = date_posted 13 | 14 | 15 | -------------------------------------------------------------------------------- /ch03/model/recipes.py: -------------------------------------------------------------------------------- 1 | 2 | from uuid import UUID 3 | from model.classifications import Category, Origin 4 | from typing import List 5 | 6 | class Ingredient: 7 | def __init__(self, id: UUID, name:str, qty : float, measure : str): 8 | self.id = id 9 | self.name = name 10 | self.qty = qty 11 | self.measure = measure 12 | 13 | 14 | class Recipe: 15 | def __init__(self, id: UUID, name:str, ingredients: List[Ingredient], cat: Category, orig : Origin): 16 | self.id = id 17 | self.name = name 18 | self.ingredients = ingredients 19 | self.cat = cat 20 | self.orig = orig -------------------------------------------------------------------------------- /ch03/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Online Recipe System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: October 20, 2021 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype aims to store various recipes on any menu to be viewed and 10 | rated by visitors. It even classifies the recipes according to the place 11 | of origin and menu type. Users may search for their desired recipe for 12 | reference, rating, and feedback purposes. It has a feature that allows 13 | users to attach keywords to each recipe for search purposes. 14 | The microservice application is an initial architecture for a robust 15 | online recipe platform. 16 | 17 | This application uses the FastAPI framework driven by Python 3.8. 18 | No database included yet. 19 | 20 | The requirements.txt will guide you with the dependencies. Just install by running: 21 | pip install -r requirements.txt 22 | -------------------------------------------------------------------------------- /ch03/repository/admin.py: -------------------------------------------------------------------------------- 1 | 2 | from repository.users import login_details, user_profiles 3 | from repository.login import logs_visitor 4 | 5 | class AdminRepository: 6 | 7 | def __init__(self): 8 | pass 9 | 10 | def query_login_details(self): 11 | return list(login_details.values()) 12 | 13 | def query_user_profiles(self): 14 | return list(user_profiles.values()) 15 | 16 | def query_logs_visitor(self): 17 | return list(logs_visitor.values()) -------------------------------------------------------------------------------- /ch03/repository/aggregates.py: -------------------------------------------------------------------------------- 1 | stats_user_type = dict() -------------------------------------------------------------------------------- /ch03/repository/complaints.py: -------------------------------------------------------------------------------- 1 | 2 | from uuid import UUID 3 | from repository.recipes import recipes 4 | recipe_bad = dict() 5 | 6 | class BadRecipeRepository: 7 | def __init__(self): 8 | pass 9 | 10 | def add_bad_recipe(self, id:UUID): 11 | recipe_bad[id] = id 12 | 13 | 14 | def query_bad_recipes(self): 15 | return list(recipe_bad.values()) -------------------------------------------------------------------------------- /ch03/repository/factory.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends 2 | from repository.recipes import RecipeRepository 3 | from repository.posts import PostRepository 4 | from repository.admin import AdminRepository 5 | from repository.keywords import KeywordRepository 6 | from repository.complaints import BadRecipeRepository 7 | 8 | def get_recipe_repo(repo=Depends(RecipeRepository)): 9 | return repo 10 | 11 | def get_post_repo(repo=Depends(PostRepository)): 12 | return repo 13 | 14 | def get_users_repo(repo=Depends(AdminRepository)): 15 | return repo 16 | 17 | def get_keywords(keywords=Depends(KeywordRepository)): 18 | return keywords 19 | 20 | def get_bad_recipes(repo=Depends(BadRecipeRepository)): 21 | return repo 22 | 23 | 24 | -------------------------------------------------------------------------------- /ch03/repository/keywords.py: -------------------------------------------------------------------------------- 1 | 2 | from uuid import UUID 3 | from typing import List 4 | 5 | keywords_recipe = dict() 6 | 7 | class KeywordRepository: 8 | 9 | def __init__(self): 10 | pass 11 | 12 | def insert_keywords(self, id:UUID, keywords: List[str]): 13 | keywords_recipe[id] = keywords 14 | 15 | def add_keywords(self, id:UUID, keyword:str): 16 | if keywords_recipe.get(id) == None: 17 | keywords = list() 18 | keywords.append(keyword) 19 | keywords_recipe[id] = keywords 20 | else: 21 | keywords = keywords_recipe[id] 22 | keywords.append(keyword) 23 | keywords_recipe[id] = keywords 24 | 25 | 26 | 27 | def query_keywords(self, id:UUID): 28 | return keywords_recipe[id] 29 | 30 | def query_all_keywords(self): 31 | return dict(keywords_recipe.items()) 32 | -------------------------------------------------------------------------------- /ch03/repository/login.py: -------------------------------------------------------------------------------- 1 | from datetime import date 2 | logs_visitor = dict() 3 | 4 | class LoginRepository: 5 | def __init__(self): 6 | pass 7 | 8 | def login_audit(self, username: str, password: str): 9 | logs_visitor[username] = date.today() 10 | -------------------------------------------------------------------------------- /ch03/repository/posts.py: -------------------------------------------------------------------------------- 1 | from datetime import date, datetime 2 | from model.classifications import RecipeRating 3 | from model.posts import Post 4 | from uuid import uuid1 5 | 6 | posts = dict() 7 | 8 | class PostRepository: 9 | def __init__(self): 10 | pass 11 | 12 | def insert_post(self, post: Post): 13 | posts[post.id] = post 14 | 15 | def query_posts(self): 16 | return list(posts.values()) -------------------------------------------------------------------------------- /ch03/repository/users.py: -------------------------------------------------------------------------------- 1 | login_details = dict() 2 | user_profiles = dict() 3 | 4 | -------------------------------------------------------------------------------- /ch03/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | dependency-injector==4.39.1 5 | fastapi==0.78.0 6 | h11==0.13.0 7 | idna==3.3 8 | lagom==1.7.1 9 | pydantic==1.9.1 10 | python-multipart==0.0.5 11 | six==1.16.0 12 | sniffio==1.2.0 13 | starlette==0.19.1 14 | typing_extensions==4.2.0 15 | uvicorn==0.18.2 16 | -------------------------------------------------------------------------------- /ch03/service/complaints.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends 2 | from repository.factory import get_bad_recipes 3 | from uuid import UUID 4 | 5 | class BadRecipeService: 6 | 7 | def __init__(self, recipes=Depends(get_bad_recipes)): 8 | self.recipes = recipes 9 | 10 | def report_bad_recipe(self, id: UUID): 11 | self.recipes.add_bad_recipe(id) 12 | 13 | def get_bad_recipes(self): 14 | return self.recipes.query_bad_recipes() -------------------------------------------------------------------------------- /ch03/service/factory.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends 2 | from service.recipes import RecipeService 3 | from service.posts import PostService 4 | from service.complaints import BadRecipeService 5 | 6 | def get_recipe_service(repo=Depends(RecipeService)): 7 | return repo 8 | 9 | def get_post_service(repo=Depends(PostService)): 10 | return repo 11 | 12 | def get_complaint_service(repo=Depends(BadRecipeService)): 13 | return repo 14 | 15 | -------------------------------------------------------------------------------- /ch03/service/posts.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends 2 | from model.posts import Post 3 | from repository.factory import get_post_repo 4 | 5 | class PostService: 6 | 7 | def __init__(self, repo=Depends(get_post_repo)): 8 | self.repo = repo 9 | 10 | def add_post(self, post: Post): 11 | self.repo.insert_post(post) 12 | 13 | def get_posts(self): 14 | return self.repo.query_posts() -------------------------------------------------------------------------------- /ch03/service/recipe_utilities.py: -------------------------------------------------------------------------------- 1 | from repository.recipes import recipes 2 | from uuid import UUID 3 | 4 | def get_recipe_names(): 5 | recipes_list = [val.name for val in recipes.values()] 6 | return recipes_list 7 | 8 | def get_recipe_ingredients(rid: UUID): 9 | ingredients = recipes[rid].ingredients 10 | return ingredients -------------------------------------------------------------------------------- /ch03/service/recipes.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends 2 | from model.recipes import Recipe 3 | from repository.factory import get_recipe_repo 4 | 5 | 6 | class RecipeService: 7 | 8 | def __init__(self, repo=Depends(get_recipe_repo)): 9 | self.repo = repo 10 | 11 | def get_recipes(self): 12 | return self.repo.query_recipes() 13 | 14 | def add_recipe(self, recipe: Recipe): 15 | self.repo.insert_recipe(recipe) 16 | 17 | -------------------------------------------------------------------------------- /ch04-faculty/configuration/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseSettings 2 | from datetime import date 3 | import os 4 | 5 | class FacultySettings(BaseSettings): 6 | application:str = 'Faculty Management System' 7 | webmaster:str = 'sjctrags@university.com' 8 | created:date = '2021-11-10' 9 | 10 | class ServerSettings(BaseSettings): 11 | production_server:str 12 | prod_port:int 13 | development_server:str 14 | dev_port:int 15 | 16 | class Config: 17 | env_file = os.getcwd() + '/configuration/erp_settings.properties' 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch04-faculty/configuration/erp_settings.properties: -------------------------------------------------------------------------------- 1 | production_server = prodserver100 2 | prod_port = 9000 3 | development_server = devserver200 4 | dev_port = 10000 5 | 6 | -------------------------------------------------------------------------------- /ch04-faculty/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, Depends 2 | from controllers import admin, assignments, books 3 | from configuration.config import FacultySettings, ServerSettings 4 | 5 | app = FastAPI() 6 | app.include_router(admin.router, prefix="/ch04/faculty") 7 | app.include_router(assignments.router, prefix="/ch04/faculty") 8 | app.include_router(books.router, prefix="/ch04/faculty") 9 | 10 | def build_config(): 11 | return FacultySettings() 12 | 13 | def fetch_config(): 14 | return ServerSettings() 15 | 16 | @app.get('/index') 17 | def index_faculty(config:FacultySettings = Depends(build_config), fconfig:ServerSettings = Depends(fetch_config)): 18 | return { 19 | 'project_name': config.application, 20 | 'webmaster': config.webmaster, 21 | 'created': config.created, 22 | 'production_server' : fconfig.production_server, 23 | 'prod_port' : fconfig.prod_port 24 | } 25 | -------------------------------------------------------------------------------- /ch04-faculty/models/data/facultydb.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | from models.data.faculty import Faculty, Assignment, Login, Signup, StudentBin 3 | faculty_tbl:Dict[int, Faculty] = dict() 4 | faculty_assignments_tbl:Dict[int, Assignment] = dict() 5 | faculty_login_tbl:Dict[int, Login ] = dict() 6 | faculty_signup_tbl:Dict[int, Signup] = dict() 7 | student_bin_tbl:Dict[int, StudentBin] = dict() -------------------------------------------------------------------------------- /ch04-faculty/models/data/library.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | class Classification(str, Enum): 4 | Non_Fiction='Non-Fiction' 5 | Fiction='Fiction' 6 | Science='Science' 7 | Technology='Technology' 8 | History='History' 9 | Arts='Arts' 10 | Music='Music' 11 | Travels='Travels' 12 | Food='Food' 13 | Engineering='Engineering' -------------------------------------------------------------------------------- /ch04-faculty/models/request/assignment.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from datetime import datetime 4 | 5 | class AssignmentRequest(BaseModel): 6 | bin_id:int 7 | assgn_id:int 8 | title:str 9 | date_completed:Optional[datetime] = None 10 | date_due:datetime 11 | rating:Optional[float] = None 12 | course:str 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch04-faculty/models/request/faculty.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from models.data.faculty import Major 4 | 5 | class SignupReq(BaseModel): 6 | faculty_id:int 7 | username:str 8 | password:str 9 | 10 | class FacultyReq(BaseModel): 11 | faculty_id:int 12 | fname:str 13 | lname:str 14 | mname:str 15 | age:int 16 | major:Major 17 | department:str 18 | 19 | class FacultyDetails(BaseModel): 20 | fname:Optional[str] = None 21 | lname:Optional[str] = None 22 | mname:Optional[str] = None 23 | age:Optional[int] = None 24 | major:Optional[Major] = None 25 | department:Optional[str] = None 26 | 27 | -------------------------------------------------------------------------------- /ch04-faculty/models/request/library.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from datetime import datetime 3 | from pydantic import BaseModel 4 | from models.data.library import Classification 5 | 6 | class BookReq(BaseModel): 7 | book_id:int 8 | title:str 9 | classification:Classification 10 | author:str 11 | year_published:datetime 12 | edition:int 13 | 14 | class BookDetails(BaseModel): 15 | title:Optional[str] = None 16 | classification:Optional[Classification] = None 17 | author:Optional[str] = None 18 | year_published:Optional[datetime] = None 19 | edition:Optional[int] = None 20 | 21 | class BookRequestReq(BaseModel): 22 | book_id:int 23 | request_date:datetime 24 | status:bool 25 | 26 | class BookIssuanceReq(BaseModel): 27 | req_id:int 28 | approved_by:str 29 | approved_date:datetime 30 | 31 | class BookReturnReq(BaseModel): 32 | issue_id:int 33 | returned_date:datetime -------------------------------------------------------------------------------- /ch04-faculty/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: University ERP System (Faculty Microservice) 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: July 19, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is the faculty microservice application which is part of the 10 | whole University ERP. This application can be run, managed, and deployed 11 | separately from the others using a different URL address and port. 12 | 13 | Please refer to project ch04 for the backup database and requirements.txt. -------------------------------------------------------------------------------- /ch04-faculty/repository/signup.py: -------------------------------------------------------------------------------- 1 | from models.data.facultydb import faculty_signup_tbl 2 | from models.data.faculty import Signup 3 | 4 | class FacultySignupRepository: 5 | 6 | def add_item(self, item: Signup): 7 | try: 8 | faculty_signup_tbl[item.sign_id] = item 9 | except: 10 | return False 11 | return True 12 | 13 | def remove_item(self, sign_id:int): 14 | try: 15 | del faculty_signup_tbl[sign_id] 16 | except: 17 | return False 18 | return True 19 | 20 | def get_item(self, sign_id:int): 21 | try: 22 | account = faculty_signup_tbl[sign_id] 23 | except: 24 | return None 25 | return account 26 | -------------------------------------------------------------------------------- /ch04-faculty/services/faculty.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict , Any 2 | from repository.faculty import FacultyRepository 3 | from models.data.faculty import Faculty 4 | 5 | class FacultyService: 6 | 7 | def __init__(self): 8 | self.repo:FacultyRepository = FacultyRepository() 9 | 10 | def add_faculty(self, faculty:Faculty): 11 | result = self.repo.insert_faculty(faculty) 12 | return result 13 | 14 | def update_faculty(self, faculty_id:int, details:Dict[str, Any]): 15 | result = self.repo.update_faculty(faculty_id, details ) 16 | return result 17 | 18 | def remove_faculty(self, faculty_id:int): 19 | result = self.repo.delete_faculty(faculty_id) 20 | return result 21 | 22 | def list_faculty(self): 23 | return self.repo.get_all_faculty() 24 | -------------------------------------------------------------------------------- /ch04-faculty/services/login.py: -------------------------------------------------------------------------------- 1 | from repository.login import FacultyLoginRepository 2 | from models.data.faculty import Login 3 | 4 | 5 | class FacultyLoginService: 6 | 7 | def __init__(self): 8 | self.repo:FacultyLoginRepository = FacultyLoginRepository() 9 | 10 | def add_faculty_login(self, login:Login): 11 | result = self.repo.insert_login(login) 12 | return result 13 | 14 | def update_login_password(self, user_id:int, newpass:str): 15 | result = self.repo.update_password_userid(user_id, newpass) 16 | return result 17 | 18 | def remove_faculty_login(self, user_id:int): 19 | result = self.repo.delete_login(user_id) 20 | return result 21 | 22 | def get_faculty_login(self, username:str): 23 | return self.repo.get_login(username) 24 | 25 | def list_login(self): 26 | return self.repo.get_all_login() -------------------------------------------------------------------------------- /ch04-faculty/services/signup.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict , Any 2 | from repository.signup import FacultySignupRepository 3 | from models.data.faculty import Signup 4 | 5 | class FacultySignupService: 6 | def __init__(self): 7 | self.repo:FacultySignupRepository = FacultySignupRepository() 8 | 9 | def add_signup(self, signup: Signup): 10 | result = self.repo.add_item(signup) 11 | return result 12 | 13 | def get_signup(self, sign_id:int): 14 | result = self.repo.get_item(sign_id) 15 | return result 16 | 17 | def remove_signup(self, sign_id:int): 18 | result = self.repo.remove_item(sign_id) 19 | return result -------------------------------------------------------------------------------- /ch04-library/configuration/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseSettings 2 | from datetime import date 3 | import os 4 | 5 | class LibrarySettings(BaseSettings): 6 | application:str = 'Library Management System' 7 | webmaster:str = 'sjctrags@university.com' 8 | created:date = '2021-11-10' 9 | 10 | 11 | class ServerSettings(BaseSettings): 12 | production_server:str 13 | prod_port:int 14 | development_server:str 15 | dev_port:int 16 | 17 | class Config: 18 | env_file = os.getcwd() + '/configuration/erp_settings.properties' 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /ch04-library/configuration/erp_settings.properties: -------------------------------------------------------------------------------- 1 | production_server = prodserver100 2 | prod_port = 9000 3 | development_server = devserver200 4 | dev_port = 10000 5 | 6 | -------------------------------------------------------------------------------- /ch04-library/main.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import FastAPI, Depends 3 | from controllers import admin, management 4 | from configuration.config import LibrarySettings 5 | 6 | app = FastAPI() 7 | app.include_router(admin.router, prefix="/ch04/library") 8 | app.include_router(management.router, prefix="/ch04/library") 9 | 10 | def build_config(): 11 | return LibrarySettings() 12 | 13 | @app.get('/index') 14 | def index_library(config:LibrarySettings = Depends(build_config) ): 15 | return { 16 | 'project_name': config.application, 17 | 'webmaster': config.webmaster, 18 | 'created': config.created 19 | } -------------------------------------------------------------------------------- /ch04-library/models/data/librarydb.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from models.data.library import Book, BookRequest, BookIssuance 4 | 5 | book_tbl:Dict[int, Book] = dict() 6 | book_request_tbl:Dict[int, BookRequest] = dict() 7 | book_issuance_tbl:Dict[int, BookIssuance] = dict() 8 | 9 | -------------------------------------------------------------------------------- /ch04-library/models/request/library.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from datetime import datetime 3 | from pydantic import BaseModel 4 | from models.data.library import Classification 5 | 6 | class BookReq(BaseModel): 7 | book_id:int 8 | title:str 9 | classification:Classification 10 | author:str 11 | year_published:datetime 12 | edition:int 13 | 14 | class BookDetails(BaseModel): 15 | title:Optional[str] = None 16 | classification:Optional[Classification] = None 17 | author:Optional[str] = None 18 | year_published:Optional[datetime] = None 19 | edition:Optional[int] = None 20 | 21 | class BookRequestReq(BaseModel): 22 | book_id:int 23 | request_date:datetime 24 | status:bool 25 | 26 | class BookIssuanceReq(BaseModel): 27 | req_id:int 28 | approved_by:str 29 | approved_date:datetime 30 | 31 | class BookReturnReq(BaseModel): 32 | issue_id:int 33 | returned_date:datetime -------------------------------------------------------------------------------- /ch04-library/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: University ERP System (Library Microservice) 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: July 19, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is the library microservice application which is part of the 10 | whole University ERP. This application can be run, managed, and deployed 11 | separately from the others using a different URL address and port. 12 | 13 | Please refer to project ch04 for the backup database and requirements.txt. -------------------------------------------------------------------------------- /ch04-library/repository/reservations.py: -------------------------------------------------------------------------------- 1 | from models.data.library import BookRequest 2 | from models.data.librarydb import book_request_tbl 3 | 4 | class BookRequestRepository: 5 | 6 | def insert_request(self, request:BookRequest): 7 | try: 8 | book_request_tbl[request.req_id] = request 9 | except: 10 | return False 11 | return True 12 | 13 | def update_requested_book(self, req_id:int, book_id:int): 14 | try: 15 | request = book_request_tbl[req_id] 16 | request.book_id = book_id 17 | except: 18 | return False 19 | return True 20 | 21 | def delete_request(self, req_id:int): 22 | try: 23 | del book_request_tbl[req_id] 24 | except: 25 | return False 26 | return True 27 | 28 | def get_all_requests(self): 29 | return book_request_tbl -------------------------------------------------------------------------------- /ch04-library/services/books.py: -------------------------------------------------------------------------------- 1 | from typing import Dict , Any 2 | from repository.books import BookRepository 3 | from models.data.library import Book 4 | 5 | class BookService: 6 | 7 | def __init__(self): 8 | self.repo:BookRepository = BookRepository() 9 | 10 | def add_book(self, book:Book): 11 | result = self.repo.insert_book(book) 12 | return result 13 | 14 | def update_book(self, book_id:int, details:Dict[str, Any]): 15 | result = self.repo.update_book(book_id, details ) 16 | return result 17 | 18 | def remove_book(self, book_id:int): 19 | result = self.repo.delete_book(book_id) 20 | return result 21 | 22 | def list_book(self): 23 | return self.repo.get_all_books() 24 | -------------------------------------------------------------------------------- /ch04-library/services/reservations.py: -------------------------------------------------------------------------------- 1 | from repository.reservations import BookRequestRepository 2 | from models.data.library import BookRequest 3 | 4 | class BookRequestService: 5 | 6 | def __init__(self): 7 | self.repo:BookRequestRepository = BookRequestRepository() 8 | 9 | def add_book_request(self, book_request:BookRequest): 10 | result = self.repo.insert_request(book_request) 11 | return result 12 | 13 | def update_book_request(self, req_id:int, book_id:int): 14 | result = self.repo.update_requested_book(req_id, book_id) 15 | return result 16 | 17 | def remove_book_request(self, req_id:int): 18 | result = self.repo.delete_request(req_id) 19 | return result 20 | 21 | def list_book_request(self): 22 | return self.repo.get_all_requests() 23 | -------------------------------------------------------------------------------- /ch04-student/configuration/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseSettings 2 | from datetime import date 3 | import os 4 | 5 | class StudentSettings(BaseSettings): 6 | application:str = 'Student Management System' 7 | webmaster:str = 'sjctrags@university.com' 8 | created:date = '2021-11-10' 9 | 10 | class ServerSettings(BaseSettings): 11 | production_server:str 12 | prod_port:int 13 | development_server:str 14 | dev_port:int 15 | 16 | class Config: 17 | env_file = os.getcwd() + '/configuration/erp_settings.properties' 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch04-student/configuration/erp_settings.properties: -------------------------------------------------------------------------------- 1 | production_server = prodserver100 2 | prod_port = 9000 3 | development_server = devserver200 4 | dev_port = 10000 5 | 6 | -------------------------------------------------------------------------------- /ch04-student/controllers/assignments.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | from fastapi.encoders import jsonable_encoder 3 | from models.request.assignment import AssignmentRequest 4 | 5 | import json 6 | import httpx 7 | 8 | router = APIRouter() 9 | 10 | @router.get('/assignment/list') 11 | async def list_assignments(): 12 | async with httpx.AsyncClient() as client: 13 | result = await client.get("http://localhost:8002/ch04/faculty/assignments/list") 14 | return result.json() 15 | 16 | @router.post('/assignment/submit') 17 | def submit_assignment(assignment:AssignmentRequest ): 18 | with httpx.Client() as client: 19 | response = client.post("http://localhost:8002/ch04/faculty/assignments/student/submit", data=json.dumps(jsonable_encoder(assignment))) 20 | return response.content 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch04-student/controllers/reservations.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import APIRouter 3 | from pydantic import BaseModel 4 | from fastapi.encoders import jsonable_encoder 5 | from json import dumps, loads 6 | import httpx 7 | from models.request.library import BookIssuanceReq 8 | 9 | router = APIRouter() 10 | 11 | @router.get('/access/book') 12 | def access_book(): 13 | with httpx.Client() as client: 14 | response = client.get("http://localhost:8001/ch04/library/book/list") 15 | return response.json() 16 | 17 | @router.post('/reserve/book') 18 | def reserve_book(book:BookIssuanceReq): 19 | with httpx.Client() as client: 20 | response = client.post("http://localhost:8001/ch04/library/book/issuance", data=dumps(jsonable_encoder(book))) 21 | return response.content -------------------------------------------------------------------------------- /ch04-student/main.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import FastAPI, Depends 3 | from controllers import reservations, admin, assignments 4 | from configuration.config import StudentSettings, ServerSettings 5 | 6 | app = FastAPI() 7 | app.include_router(reservations.router, prefix="/ch04/student") 8 | app.include_router(admin.router, prefix="/ch04/student") 9 | app.include_router(assignments.router, prefix="/ch04/student") 10 | 11 | def build_config(): 12 | return StudentSettings() 13 | 14 | def fetch_config(): 15 | return ServerSettings() 16 | 17 | @app.get('/index') 18 | def index_student(config:StudentSettings = Depends(build_config), fconfig:ServerSettings = Depends(fetch_config)): 19 | return { 20 | 'project_name': config.application, 21 | 'webmaster': config.webmaster, 22 | 'created': config.created, 23 | 'development_server' : fconfig.development_server, 24 | 'dev_port': fconfig.dev_port 25 | } -------------------------------------------------------------------------------- /ch04-student/models/data/library.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | class Classification(str, Enum): 4 | Non_Fiction='Non-Fiction' 5 | Fiction='Fiction' 6 | Science='Science' 7 | Technology='Technology' 8 | History='History' 9 | Arts='Arts' 10 | Music='Music' 11 | Travels='Travels' 12 | Food='Food' 13 | Engineering='Engineering' -------------------------------------------------------------------------------- /ch04-student/models/data/studentsdb.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | from models.data.students import Login, Student, Signup, Assignment 3 | 4 | students_tbl:Dict[int, Student] = dict() 5 | stud_login_tbl:Dict[int, Login ] = dict() 6 | stud_signup_tbl:Dict[int, Signup] = dict() 7 | 8 | -------------------------------------------------------------------------------- /ch04-student/models/request/assignment.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from datetime import datetime 4 | 5 | class AssignmentRequest(BaseModel): 6 | bin_id:int 7 | assgn_id:int 8 | title:str 9 | date_completed:Optional[datetime] = None 10 | date_due:datetime 11 | rating:Optional[float] = None 12 | course:str 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch04-student/models/request/library.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from datetime import datetime 3 | from pydantic import BaseModel 4 | from models.data.library import Classification 5 | 6 | class BookReq(BaseModel): 7 | book_id:int 8 | title:str 9 | classification:Classification 10 | author:str 11 | year_published:datetime 12 | edition:int 13 | 14 | class BookDetails(BaseModel): 15 | title:Optional[str] = None 16 | classification:Optional[Classification] = None 17 | author:Optional[str] = None 18 | year_published:Optional[datetime] = None 19 | edition:Optional[int] = None 20 | 21 | class BookRequestReq(BaseModel): 22 | book_id:int 23 | request_date:datetime 24 | status:bool 25 | 26 | class BookIssuanceReq(BaseModel): 27 | req_id:int 28 | approved_by:str 29 | approved_date:datetime 30 | 31 | class BookReturnReq(BaseModel): 32 | issue_id:int 33 | returned_date:datetime -------------------------------------------------------------------------------- /ch04-student/models/request/students.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from models.data.students import StudentStatus, Major 4 | 5 | class SignupReq(BaseModel): 6 | stud_id:int 7 | username:str 8 | password:str 9 | 10 | class StudentReq(BaseModel): 11 | stud_id:int 12 | fname:str 13 | lname:str 14 | mname:str 15 | age:int 16 | major:Major 17 | department:str 18 | status:StudentStatus 19 | 20 | class StudentDetails(BaseModel): 21 | fname:Optional[str] = None 22 | lname:Optional[str] = None 23 | mname:Optional[str] = None 24 | age:Optional[int] = None 25 | major:Optional[Major] = None 26 | department:Optional[str] = None 27 | status:Optional[StudentStatus] = None -------------------------------------------------------------------------------- /ch04-student/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: University ERP System (Student Microservice) 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: July 19, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is the student microservice application which is part of the 10 | whole University ERP. This application can be run, managed, and deployed 11 | separately from the others using a different URL address and port. 12 | 13 | Please refer to project ch04 for the backup database and requirements.txt. -------------------------------------------------------------------------------- /ch04-student/repository/signup.py: -------------------------------------------------------------------------------- 1 | from models.data.studentsdb import stud_signup_tbl 2 | from models.data.students import Signup 3 | 4 | class StudentSignupRepository: 5 | 6 | def insert_item(self, item: Signup): 7 | try: 8 | stud_signup_tbl[item.sign_id] = item 9 | except: 10 | return False 11 | return True 12 | 13 | def delete_item(self, sign_id:int): 14 | try: 15 | del stud_signup_tbl[sign_id] 16 | except: 17 | return False 18 | return True 19 | 20 | def get_item(self, sign_id:int): 21 | try: 22 | account = stud_signup_tbl[sign_id] 23 | except: 24 | return None 25 | return account 26 | 27 | -------------------------------------------------------------------------------- /ch04-student/services/login.py: -------------------------------------------------------------------------------- 1 | from repository.login import StudentLoginRepository 2 | from models.data.students import Login 3 | 4 | class StudentLoginService: 5 | 6 | def __init__(self): 7 | self.repo:StudentLoginRepository = StudentLoginRepository() 8 | 9 | def add_student_login(self, login:Login): 10 | result = self.repo.insert_login(login) 11 | return result 12 | 13 | def update_login_password(self, user_id:int, newpass:str): 14 | result = self.repo.update_password(user_id, newpass) 15 | return result 16 | 17 | def remove_student_login(self, user_id:int): 18 | result = self.repo.delete_login(user_id) 19 | return result 20 | 21 | def get_student_login(self, username): 22 | return self.repo.get_login(username) 23 | 24 | def list_login(self): 25 | return self.repo.get_all_login() -------------------------------------------------------------------------------- /ch04-student/services/signup.py: -------------------------------------------------------------------------------- 1 | from repository.signup import StudentSignupRepository 2 | from models.data.students import Signup 3 | 4 | class StudentSignupService: 5 | 6 | def __init__(self): 7 | self.repo:StudentSignupRepository = StudentSignupRepository() 8 | 9 | def add_signup(self, signup: Signup): 10 | result = self.repo.insert_item(signup) 11 | return result 12 | 13 | def get_signup(self, sign_id:int): 14 | result = self.repo.get_item(sign_id) 15 | return result 16 | 17 | def remove_signup(self, sign_id:int): 18 | result = self.repo.delete_item(sign_id) 19 | return result -------------------------------------------------------------------------------- /ch04-student/services/students.py: -------------------------------------------------------------------------------- 1 | from typing import Dict , Any 2 | from repository.students import StudentRepository 3 | from models.data.students import Student 4 | 5 | class StudentService: 6 | 7 | def __init__(self): 8 | self.repo:StudentRepository = StudentRepository() 9 | 10 | def add_student(self, student:Student): 11 | result = self.repo.insert_student(student) 12 | return result 13 | 14 | def update_student(self, stud_id:int, details:Dict[str, Any]): 15 | result = self.repo.update_student(stud_id, details) 16 | return result 17 | 18 | def remove_student(self, stud_id:int): 19 | result = self.repo.delete_student(stud_id) 20 | return result 21 | 22 | def list_students(self): 23 | return self.repo.get_all_students() 24 | 25 | -------------------------------------------------------------------------------- /ch04/configuration/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseSettings 2 | from datetime import date 3 | import os 4 | 5 | class FacultySettings(BaseSettings): 6 | application:str = 'Faculty Management System' 7 | webmaster:str = 'sjctrags@university.com' 8 | created:date = '2021-11-10' 9 | 10 | class LibrarySettings(BaseSettings): 11 | application:str = 'Library Management System' 12 | webmaster:str = 'sjctrags@university.com' 13 | created:date = '2021-11-10' 14 | 15 | 16 | class StudentSettings(BaseSettings): 17 | application:str = 'Student Management System' 18 | webmaster:str = 'sjctrags@university.com' 19 | created:date = '2021-11-10' 20 | 21 | class ServerSettings(BaseSettings): 22 | production_server:str 23 | prod_port:int 24 | development_server:str 25 | dev_port:int 26 | 27 | class Config: 28 | env_file = os.getcwd() + '/configuration/erp_settings.properties' 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ch04/configuration/erp_settings.properties: -------------------------------------------------------------------------------- 1 | production_server = prodserver100 2 | prod_port = 9000 3 | development_server = devserver200 4 | dev_port = 10000 5 | 6 | -------------------------------------------------------------------------------- /ch04/controller/university.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | 3 | router = APIRouter() 4 | 5 | @router.get("/university/{portal_id}") 6 | def access_portal(portal_id:int): 7 | return {'message': 'University ERP Systems'} 8 | 9 | -------------------------------------------------------------------------------- /ch04/faculty_mgt/faculty_main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, Depends 2 | from faculty_mgt.controllers import admin, assignments, books 3 | from configuration.config import FacultySettings, ServerSettings 4 | 5 | faculty_app = FastAPI() 6 | faculty_app.include_router(admin.router) 7 | faculty_app.include_router(assignments.router) 8 | faculty_app.include_router(books.router) 9 | 10 | def build_config(): 11 | return FacultySettings() 12 | 13 | def fetch_config(): 14 | return ServerSettings() 15 | 16 | @faculty_app.get('/index') 17 | def index_faculty(config:FacultySettings = Depends(build_config), fconfig:ServerSettings = Depends(fetch_config)): 18 | return { 19 | 'project_name': config.application, 20 | 'webmaster': config.webmaster, 21 | 'created': config.created, 22 | 'production_server' : fconfig.production_server, 23 | 'prod_port' : fconfig.prod_port 24 | } 25 | -------------------------------------------------------------------------------- /ch04/faculty_mgt/models/data/facultydb.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | from faculty_mgt.models.data.faculty import Faculty, Assignment, Login, Signup, StudentBin 3 | faculty_tbl:Dict[int, Faculty] = dict() 4 | faculty_assignments_tbl:Dict[int, Assignment] = dict() 5 | faculty_login_tbl:Dict[int, Login ] = dict() 6 | faculty_signup_tbl:Dict[int, Signup] = dict() 7 | student_bin_tbl:Dict[int, StudentBin] = dict() -------------------------------------------------------------------------------- /ch04/faculty_mgt/models/request/assignment.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from datetime import datetime 4 | 5 | class AssignmentRequest(BaseModel): 6 | bin_id:int 7 | assgn_id:int 8 | title:str 9 | date_completed:Optional[datetime] = None 10 | date_due:datetime 11 | rating:Optional[float] = None 12 | course:str 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch04/faculty_mgt/models/request/faculty.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from faculty_mgt.models.data.faculty import Major 4 | 5 | class SignupReq(BaseModel): 6 | faculty_id:int 7 | username:str 8 | password:str 9 | 10 | class FacultyReq(BaseModel): 11 | faculty_id:int 12 | fname:str 13 | lname:str 14 | mname:str 15 | age:int 16 | major:Major 17 | department:str 18 | 19 | class FacultyDetails(BaseModel): 20 | fname:Optional[str] = None 21 | lname:Optional[str] = None 22 | mname:Optional[str] = None 23 | age:Optional[int] = None 24 | major:Optional[Major] = None 25 | department:Optional[str] = None 26 | 27 | -------------------------------------------------------------------------------- /ch04/faculty_mgt/models/request/library.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from datetime import datetime 3 | from pydantic import BaseModel 4 | from library_mgt.models.data.library import Classification 5 | 6 | class BookReq(BaseModel): 7 | book_id:int 8 | title:str 9 | classification:Classification 10 | author:str 11 | year_published:datetime 12 | edition:int 13 | 14 | class BookDetails(BaseModel): 15 | title:Optional[str] = None 16 | classification:Optional[Classification] = None 17 | author:Optional[str] = None 18 | year_published:Optional[datetime] = None 19 | edition:Optional[int] = None 20 | 21 | class BookRequestReq(BaseModel): 22 | book_id:int 23 | request_date:datetime 24 | status:bool 25 | 26 | class BookIssuanceReq(BaseModel): 27 | req_id:int 28 | approved_by:str 29 | approved_date:datetime 30 | 31 | class BookReturnReq(BaseModel): 32 | issue_id:int 33 | returned_date:datetime -------------------------------------------------------------------------------- /ch04/faculty_mgt/repository/signup.py: -------------------------------------------------------------------------------- 1 | from faculty_mgt.models.data.facultydb import faculty_signup_tbl 2 | from faculty_mgt.models.data.faculty import Signup 3 | 4 | class FacultySignupRepository: 5 | 6 | def add_item(self, item: Signup): 7 | try: 8 | faculty_signup_tbl[item.sign_id] = item 9 | except: 10 | return False 11 | return True 12 | 13 | def remove_item(self, sign_id:int): 14 | try: 15 | del faculty_signup_tbl[sign_id] 16 | except: 17 | return False 18 | return True 19 | 20 | def get_item(self, sign_id:int): 21 | try: 22 | account = faculty_signup_tbl[sign_id] 23 | except: 24 | return None 25 | return account 26 | -------------------------------------------------------------------------------- /ch04/faculty_mgt/services/faculty.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict , Any 2 | from faculty_mgt.repository.faculty import FacultyRepository 3 | from faculty_mgt.models.data.faculty import Faculty 4 | 5 | class FacultyService: 6 | 7 | def __init__(self): 8 | self.repo:FacultyRepository = FacultyRepository() 9 | 10 | def add_faculty(self, faculty:Faculty): 11 | result = self.repo.insert_faculty(faculty) 12 | return result 13 | 14 | def update_faculty(self, faculty_id:int, details:Dict[str, Any]): 15 | result = self.repo.update_faculty(faculty_id, details ) 16 | return result 17 | 18 | def remove_faculty(self, faculty_id:int): 19 | result = self.repo.delete_faculty(faculty_id) 20 | return result 21 | 22 | def list_faculty(self): 23 | return self.repo.get_all_faculty() 24 | -------------------------------------------------------------------------------- /ch04/faculty_mgt/services/login.py: -------------------------------------------------------------------------------- 1 | from faculty_mgt.repository.login import FacultyLoginRepository 2 | from faculty_mgt.models.data.faculty import Login 3 | 4 | 5 | class FacultyLoginService: 6 | 7 | def __init__(self): 8 | self.repo:FacultyLoginRepository = FacultyLoginRepository() 9 | 10 | def add_faculty_login(self, login:Login): 11 | result = self.repo.insert_login(login) 12 | return result 13 | 14 | def update_login_password(self, user_id:int, newpass:str): 15 | result = self.repo.update_password(user_id, newpass) 16 | return result 17 | 18 | def remove_faculty_login(self, user_id:int): 19 | result = self.repo.delete_login(user_id) 20 | return result 21 | 22 | def get_faculty_login(self, username): 23 | return self.repo.get_login(username) 24 | 25 | def list_login(self): 26 | return self.repo.get_all_login() -------------------------------------------------------------------------------- /ch04/faculty_mgt/services/signup.py: -------------------------------------------------------------------------------- 1 | from typing import List, Dict , Any 2 | from faculty_mgt.repository.signup import FacultySignupRepository 3 | from faculty_mgt.models.data.faculty import Signup 4 | 5 | class FacultySignupService: 6 | def __init__(self): 7 | self.repo:FacultySignupRepository = FacultySignupRepository() 8 | 9 | def add_signup(self, signup: Signup): 10 | result = self.repo.insert_item(signup) 11 | return result 12 | 13 | def get_signup(self, sign_id:int): 14 | result = self.repo.get_item(sign_id) 15 | return result 16 | 17 | def remove_signup(self, sign_id:int): 18 | result = self.repo.delete_item(sign_id) 19 | return result -------------------------------------------------------------------------------- /ch04/gateway/api_router.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from fastapi import Request 3 | 4 | logger = logging.getLogger('uvicorn.access') 5 | 6 | def call_api_gateway(request: Request): 7 | portal_id = request.path_params['portal_id'] 8 | print(request.path_params) 9 | if portal_id == str(1): 10 | raise RedirectStudentPortalException() 11 | elif portal_id == str(2): 12 | raise RedirectFacultyPortalException() 13 | elif portal_id == str(3): 14 | raise RedirectLibraryPortalException() 15 | 16 | 17 | class RedirectStudentPortalException(Exception): 18 | pass 19 | 20 | class RedirectFacultyPortalException(Exception): 21 | pass 22 | 23 | class RedirectLibraryPortalException(Exception): 24 | pass 25 | -------------------------------------------------------------------------------- /ch04/library_mgt/library_main.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import FastAPI, Depends 3 | from library_mgt.controllers import admin, management 4 | from configuration.config import LibrarySettings 5 | 6 | library_app = FastAPI() 7 | library_app.include_router(admin.router) 8 | library_app.include_router(management.router) 9 | 10 | def build_config(): 11 | return LibrarySettings() 12 | 13 | @library_app.get('/index') 14 | def index_library(config:LibrarySettings = Depends(build_config) ): 15 | return { 16 | 'project_name': config.application, 17 | 'webmaster': config.webmaster, 18 | 'created': config.created 19 | } -------------------------------------------------------------------------------- /ch04/library_mgt/models/data/librarydb.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from library_mgt.models.data.library import Book, BookRequest, BookIssuance 4 | 5 | book_tbl:Dict[int, Book] = dict() 6 | book_request_tbl:Dict[int, BookRequest] = dict() 7 | book_issuance_tbl:Dict[int, BookIssuance] = dict() 8 | 9 | -------------------------------------------------------------------------------- /ch04/library_mgt/models/request/library.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from datetime import datetime 3 | from pydantic import BaseModel 4 | from library_mgt.models.data.library import Classification 5 | 6 | class BookReq(BaseModel): 7 | book_id:int 8 | title:str 9 | classification:Classification 10 | author:str 11 | year_published:datetime 12 | edition:int 13 | 14 | class BookDetails(BaseModel): 15 | title:Optional[str] = None 16 | classification:Optional[Classification] = None 17 | author:Optional[str] = None 18 | year_published:Optional[datetime] = None 19 | edition:Optional[int] = None 20 | 21 | class BookRequestReq(BaseModel): 22 | book_id:int 23 | request_date:datetime 24 | status:bool 25 | 26 | class BookIssuanceReq(BaseModel): 27 | req_id:int 28 | approved_by:str 29 | approved_date:datetime 30 | 31 | class BookReturnReq(BaseModel): 32 | issue_id:int 33 | returned_date:datetime -------------------------------------------------------------------------------- /ch04/library_mgt/repository/reservations.py: -------------------------------------------------------------------------------- 1 | from library_mgt.models.data.library import BookRequest 2 | from library_mgt.models.data.librarydb import book_request_tbl 3 | 4 | class BookRequestRepository: 5 | 6 | def insert_request(self, request:BookRequest): 7 | try: 8 | book_request_tbl[request.req_id] = request 9 | except: 10 | return False 11 | return True 12 | 13 | def update_requested_book(self, req_id:int, book_id:int): 14 | try: 15 | request = book_request_tbl[req_id] 16 | request.book_id = book_id 17 | except: 18 | return False 19 | return True 20 | 21 | def delete_request(self, req_id:int): 22 | try: 23 | del book_request_tbl[req_id] 24 | except: 25 | return False 26 | return True 27 | 28 | def get_all_requests(self): 29 | return book_request_tbl -------------------------------------------------------------------------------- /ch04/library_mgt/services/books.py: -------------------------------------------------------------------------------- 1 | from typing import Dict , Any 2 | from library_mgt.repository.books import BookRepository 3 | from library_mgt.models.data.library import Book 4 | 5 | class BookService: 6 | 7 | def __init__(self): 8 | self.repo:BookRepository = BookRepository() 9 | 10 | def add_book(self, book:Book): 11 | result = self.repo.insert_book(book) 12 | return result 13 | 14 | def update_book(self, book_id:int, details:Dict[str, Any]): 15 | result = self.repo.update_book(book_id, details ) 16 | return result 17 | 18 | def remove_book(self, book_id:int): 19 | result = self.repo.delete_book(book_id) 20 | return result 21 | 22 | def list_book(self): 23 | return self.repo.get_all_books() 24 | -------------------------------------------------------------------------------- /ch04/library_mgt/services/reservations.py: -------------------------------------------------------------------------------- 1 | from library_mgt.repository.reservations import BookRequestRepository 2 | from library_mgt.models.data.library import BookRequest 3 | 4 | class BookRequestService: 5 | 6 | def __init__(self): 7 | self.repo:BookRequestRepository = BookRequestRepository() 8 | 9 | def add_book_request(self, book_request:BookRequest): 10 | result = self.repo.insert_request(book_request) 11 | return result 12 | 13 | def update_book_request(self, req_id:int, book_id:int): 14 | result = self.repo.update_requested_book(req_id, book_id) 15 | return result 16 | 17 | def remove_book_request(self, req_id:int): 18 | result = self.repo.delete_request(req_id) 19 | return result 20 | 21 | def list_book_request(self): 22 | return self.repo.get_all_requests() 23 | -------------------------------------------------------------------------------- /ch04/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | certifi==2022.6.15 3 | charset-normalizer==2.0.12 4 | click==8.1.3 5 | colorama==0.4.5 6 | fastapi==0.78.0 7 | h11==0.12.0 8 | httpcore==0.15.0 9 | httpx==0.23.0 10 | idna==3.3 11 | loguru==0.6.0 12 | pydantic==1.9.1 13 | python-dotenv==0.20.0 14 | python-multipart==0.0.5 15 | requests==2.28.0 16 | rfc3986==1.5.0 17 | six==1.16.0 18 | sniffio==1.2.0 19 | starlette==0.19.1 20 | typing_extensions==4.2.0 21 | urllib3==1.26.9 22 | uvicorn==0.18.2 23 | win32-setctime==1.1.0 24 | -------------------------------------------------------------------------------- /ch04/student_mgt/controllers/assignments.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | from fastapi.encoders import jsonable_encoder 3 | from student_mgt.models.request.assignment import AssignmentRequest 4 | 5 | import json 6 | import httpx 7 | 8 | router = APIRouter() 9 | 10 | @router.get('/assignment/list') 11 | async def list_assignments(): 12 | with httpx.Client() as client: 13 | response = await client.get("http://localhost:8000/ch04/faculty/assignments/list") 14 | return response.json() 15 | 16 | @router.post('/assignment/submit') 17 | def submit_assignment(assignment:AssignmentRequest ): 18 | with httpx.Client() as client: 19 | response = client.post("http://localhost:8000/ch04/faculty/assignments/student/submit", data=json.dumps(jsonable_encoder(assignment))) 20 | return response.content 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch04/student_mgt/controllers/reservations.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import APIRouter 3 | from pydantic import BaseModel 4 | from fastapi.encoders import jsonable_encoder 5 | from json import dumps 6 | import httpx 7 | from student_mgt.models.request.library import BookIssuanceReq 8 | 9 | router = APIRouter() 10 | 11 | @router.get('/access/book') 12 | def access_book(): 13 | with httpx.Client() as client: 14 | response = client.get("http://localhost:8000/ch04/library/book/list") 15 | return response.json() 16 | 17 | @router.get('/reserve/book') 18 | def reserve_book(book:BookIssuanceReq): 19 | with httpx.Client() as client: 20 | response = client.post("http://localhost:8000/ch04/library/book/issuance", data={"book":dumps(jsonable_encoder(book))}) 21 | return response.content -------------------------------------------------------------------------------- /ch04/student_mgt/models/data/studentsdb.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | from student_mgt.models.data.students import Login, Student, Signup, Assignment 3 | 4 | students_tbl:Dict[int, Student] = dict() 5 | stud_login_tbl:Dict[int, Login ] = dict() 6 | stud_signup_tbl:Dict[int, Signup] = dict() 7 | 8 | -------------------------------------------------------------------------------- /ch04/student_mgt/models/request/assignment.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from datetime import datetime 4 | 5 | class AssignmentRequest(BaseModel): 6 | bin_id:int 7 | assgn_id:int 8 | title:str 9 | date_completed:Optional[datetime] = None 10 | date_due:datetime 11 | rating:Optional[float] = None 12 | course:str 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch04/student_mgt/models/request/library.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from datetime import datetime 3 | from pydantic import BaseModel 4 | from library_mgt.models.data.library import Classification 5 | 6 | class BookReq(BaseModel): 7 | book_id:int 8 | title:str 9 | classification:Classification 10 | author:str 11 | year_published:datetime 12 | edition:int 13 | 14 | class BookDetails(BaseModel): 15 | title:Optional[str] = None 16 | classification:Optional[Classification] = None 17 | author:Optional[str] = None 18 | year_published:Optional[datetime] = None 19 | edition:Optional[int] = None 20 | 21 | class BookRequestReq(BaseModel): 22 | book_id:int 23 | request_date:datetime 24 | status:bool 25 | 26 | class BookIssuanceReq(BaseModel): 27 | req_id:int 28 | approved_by:str 29 | approved_date:datetime 30 | 31 | class BookReturnReq(BaseModel): 32 | issue_id:int 33 | returned_date:datetime -------------------------------------------------------------------------------- /ch04/student_mgt/models/request/students.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Optional 3 | from student_mgt.models.data.students import StudentStatus, Major 4 | 5 | class SignupReq(BaseModel): 6 | stud_id:int 7 | username:str 8 | password:str 9 | 10 | class StudentReq(BaseModel): 11 | stud_id:int 12 | fname:str 13 | lname:str 14 | mname:str 15 | age:int 16 | major:Major 17 | department:str 18 | status:StudentStatus 19 | 20 | class StudentDetails(BaseModel): 21 | fname:Optional[str] = None 22 | lname:Optional[str] = None 23 | mname:Optional[str] = None 24 | age:Optional[int] = None 25 | major:Optional[Major] = None 26 | department:Optional[str] = None 27 | status:Optional[StudentStatus] = None -------------------------------------------------------------------------------- /ch04/student_mgt/repository/signup.py: -------------------------------------------------------------------------------- 1 | from student_mgt.models.data.studentsdb import stud_signup_tbl 2 | from student_mgt.models.data.students import Signup 3 | 4 | class StudentSignupRepository: 5 | 6 | def insert_item(self, item: Signup): 7 | try: 8 | stud_signup_tbl[item.sign_id] = item 9 | except: 10 | return False 11 | return True 12 | 13 | def delete_item(self, sign_id:int): 14 | try: 15 | del stud_signup_tbl[sign_id] 16 | except: 17 | return False 18 | return True 19 | 20 | def get_item(self, sign_id:int): 21 | try: 22 | account = stud_signup_tbl[sign_id] 23 | except: 24 | return None 25 | return account 26 | 27 | -------------------------------------------------------------------------------- /ch04/student_mgt/services/login.py: -------------------------------------------------------------------------------- 1 | from student_mgt.repository.login import StudentLoginRepository 2 | from student_mgt.models.data.students import Login 3 | 4 | class StudentLoginService: 5 | 6 | def __init__(self): 7 | self.repo:StudentLoginRepository = StudentLoginRepository() 8 | 9 | def add_student_login(self, login:Login): 10 | result = self.repo.insert_login(login) 11 | return result 12 | 13 | def update_login_password(self, user_id:int, newpass:str): 14 | result = self.repo.update_password(user_id, newpass) 15 | return result 16 | 17 | def remove_student_login(self, user_id:int): 18 | result = self.repo.delete_login(user_id) 19 | return result 20 | 21 | def get_student_login(self, username): 22 | return self.repo.get_login(username) 23 | 24 | def list_login(self): 25 | return self.repo.get_all_login() -------------------------------------------------------------------------------- /ch04/student_mgt/services/signup.py: -------------------------------------------------------------------------------- 1 | from student_mgt.repository.signup import StudentSignupRepository 2 | from student_mgt.models.data.students import Signup 3 | 4 | class StudentSignupService: 5 | 6 | def __init__(self): 7 | self.repo:StudentSignupRepository = StudentSignupRepository() 8 | 9 | def add_signup(self, signup: Signup): 10 | result = self.repo.insert_item(signup) 11 | return result 12 | 13 | def get_signup(self, sign_id:int): 14 | result = self.repo.get_item(sign_id) 15 | return result 16 | 17 | def remove_signup(self, sign_id:int): 18 | result = self.repo.delete_item(sign_id) 19 | return result -------------------------------------------------------------------------------- /ch04/student_mgt/services/students.py: -------------------------------------------------------------------------------- 1 | from typing import Dict , Any 2 | from student_mgt.repository.students import StudentRepository 3 | from student_mgt.models.data.students import Student 4 | 5 | class StudentService: 6 | 7 | def __init__(self): 8 | self.repo:StudentRepository = StudentRepository() 9 | 10 | def add_student(self, student:Student): 11 | result = self.repo.insert_student(student) 12 | return result 13 | 14 | def update_student(self, stud_id:int, details:Dict[str, Any]): 15 | result = self.repo.update_student(stud_id, details) 16 | return result 17 | 18 | def remove_student(self, stud_id:int): 19 | result = self.repo.delete_student(stud_id) 20 | return result 21 | 22 | def list_students(self): 23 | return self.repo.get_all_students() 24 | 25 | -------------------------------------------------------------------------------- /ch04/student_mgt/student_main.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import FastAPI, Depends 3 | from student_mgt.controllers import reservations, admin, assignments 4 | from configuration.config import StudentSettings, ServerSettings 5 | 6 | student_app = FastAPI() 7 | student_app.include_router(reservations.router) 8 | student_app.include_router(admin.router) 9 | student_app.include_router(assignments.router) 10 | 11 | def build_config(): 12 | return StudentSettings() 13 | 14 | def fetch_config(): 15 | return ServerSettings() 16 | 17 | @student_app.get('/index') 18 | def index_student(config:StudentSettings = Depends(build_config), fconfig:ServerSettings = Depends(fetch_config)): 19 | return { 20 | 'project_name': config.application, 21 | 'webmaster': config.webmaster, 22 | 'created': config.created, 23 | 'development_server' : fconfig.development_server, 24 | 'dev_port': fconfig.dev_port 25 | } -------------------------------------------------------------------------------- /ch05a/cqrs/commands.py: -------------------------------------------------------------------------------- 1 | 2 | from typing import Dict, Any 3 | 4 | class ProfileTrainerCommand: 5 | 6 | def __init__(self): 7 | self._details:Dict[str,Any] = dict() 8 | 9 | @property 10 | def details(self): 11 | return self._details 12 | 13 | @details.setter 14 | def details(self, details): 15 | self._details = details -------------------------------------------------------------------------------- /ch05a/cqrs/handlers.py: -------------------------------------------------------------------------------- 1 | 2 | class IQueryHandler: 3 | pass 4 | 5 | class ICommandHandler: 6 | pass -------------------------------------------------------------------------------- /ch05a/cqrs/queries.py: -------------------------------------------------------------------------------- 1 | from typing import List, Any, Optional 2 | from models.data.gino_models import Profile_Trainers 3 | 4 | class ProfileTrainerListQuery: 5 | 6 | def __init__(self): 7 | self._records:List[Profile_Trainers] = list() 8 | 9 | @property 10 | def records(self): 11 | return self._records 12 | 13 | @records.setter 14 | def records(self, records): 15 | self._records = records 16 | 17 | 18 | class ProfileTrainerRecordQuery: 19 | 20 | def __init__(self): 21 | self._record:Profile_Trainers = None 22 | 23 | @property 24 | def record(self): 25 | return self._record 26 | 27 | @record.setter 28 | def record(self, record): 29 | self._record = record -------------------------------------------------------------------------------- /ch05a/cqrs/trainers/command/create_handlers.py: -------------------------------------------------------------------------------- 1 | 2 | from cqrs.handlers import ICommandHandler 3 | from repository.gino.trainers import TrainerRepository 4 | from cqrs.commands import ProfileTrainerCommand 5 | 6 | 7 | class AddTrainerCommandHandler(ICommandHandler): 8 | 9 | def __init__(self): 10 | self.repo:TrainerRepository = TrainerRepository() 11 | 12 | async def handle(self, command:ProfileTrainerCommand) -> bool: 13 | result = await self.repo.insert_trainer(command.details) 14 | return result -------------------------------------------------------------------------------- /ch05a/cqrs/trainers/command/delete_handlers.py: -------------------------------------------------------------------------------- 1 | 2 | from cqrs.handlers import ICommandHandler 3 | from repository.gino.trainers import TrainerRepository 4 | from cqrs.commands import ProfileTrainerCommand 5 | 6 | 7 | class DeleteTrainerCommandHandler(ICommandHandler): 8 | 9 | def __init__(self): 10 | self.repo:TrainerRepository = TrainerRepository() 11 | 12 | async def handle(self, command:ProfileTrainerCommand) -> bool: 13 | result = await self.repo.delete_trainer(command.details.get("id")) 14 | return result -------------------------------------------------------------------------------- /ch05a/cqrs/trainers/command/update_handlers.py: -------------------------------------------------------------------------------- 1 | 2 | from cqrs.handlers import ICommandHandler 3 | from repository.gino.trainers import TrainerRepository 4 | from cqrs.commands import ProfileTrainerCommand 5 | 6 | 7 | class UpdateTrainerCommandHandler(ICommandHandler): 8 | 9 | def __init__(self): 10 | self.repo:TrainerRepository = TrainerRepository() 11 | 12 | async def handle(self, command:ProfileTrainerCommand) -> bool: 13 | result = await self.repo.update_trainer(command.details) 14 | return result -------------------------------------------------------------------------------- /ch05a/cqrs/trainers/query/query_handlers.py: -------------------------------------------------------------------------------- 1 | from cqrs.handlers import IQueryHandler 2 | from repository.gino.trainers import TrainerRepository 3 | from cqrs.queries import ProfileTrainerListQuery, ProfileTrainerRecordQuery 4 | 5 | class ListTrainerQueryHandler(IQueryHandler): 6 | def __init__(self): 7 | self.repo:TrainerRepository = TrainerRepository() 8 | self.query:ProfileTrainerListQuery = ProfileTrainerListQuery() 9 | 10 | async def handle(self) -> ProfileTrainerListQuery: 11 | data = await self.repo.get_all_member(); 12 | self.query.records = data 13 | return self.query 14 | 15 | 16 | class RecordTrainerQueryHandler(IQueryHandler): 17 | def __init__(self): 18 | self.repo:TrainerRepository = TrainerRepository() 19 | self.query:ProfileTrainerRecordQuery = ProfileTrainerRecordQuery() 20 | 21 | async def handle(self, id) -> ProfileTrainerListQuery: 22 | data = await self.repo.get_member(id); 23 | self.query.record = data 24 | return self.query -------------------------------------------------------------------------------- /ch05a/database/fcms-erd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch05a/database/fcms-erd.png -------------------------------------------------------------------------------- /ch05a/db_config/gino_connect.py: -------------------------------------------------------------------------------- 1 | from gino import Gino 2 | 3 | db = Gino() 4 | 5 | -------------------------------------------------------------------------------- /ch05a/db_config/pony_connect.py: -------------------------------------------------------------------------------- 1 | from pony.orm import Database 2 | 3 | db = Database("postgres", host="localhost", port="5433", user="postgres", password="admin2255", database="fcms") -------------------------------------------------------------------------------- /ch05a/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/fcms" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | -------------------------------------------------------------------------------- /ch05a/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | from api import admin, members, trainers, login 4 | 5 | 6 | 7 | app = FastAPI() 8 | app.include_router(admin.router, prefix='/ch05') 9 | app.include_router(members.router, prefix='/ch05') 10 | app.include_router(trainers.router, prefix='/ch05') 11 | app.include_router(login.router, prefix='/ch05') 12 | -------------------------------------------------------------------------------- /ch05a/models/requests/attendance.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class AttendanceMemberReq(BaseModel): 5 | id: int 6 | member_id: int 7 | timeout:int 8 | timein:int 9 | date_log:date -------------------------------------------------------------------------------- /ch05a/models/requests/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class LoginReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | date_approved:date 9 | user_type:int 10 | 11 | class Config: 12 | orm_mode = True 13 | 14 | -------------------------------------------------------------------------------- /ch05a/models/requests/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch05a/models/requests/trainers.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class ProfileTrainersReq(BaseModel): 4 | id: int 5 | firstname: str 6 | lastname: str 7 | age: int 8 | position: str 9 | tenure: float 10 | shift: int 11 | 12 | class Config: 13 | orm_mode = True -------------------------------------------------------------------------------- /ch05a/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | asyncpg==0.26.0 3 | click==8.1.3 4 | colorama==0.4.5 5 | fastapi==0.78.0 6 | gino==1.0.1 7 | greenlet==1.1.2 8 | h11==0.13.0 9 | idna==3.3 10 | pony==0.7.16 11 | psycopg2==2.9.3 12 | pydantic==1.9.1 13 | python-multipart==0.0.5 14 | six==1.16.0 15 | sniffio==1.2.0 16 | SQLAlchemy==1.3.24 17 | starlette==0.19.1 18 | typing_extensions==4.3.0 19 | uvicorn==0.18.2 20 | -------------------------------------------------------------------------------- /ch05b/database/fcms-erd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch05b/database/fcms-erd.png -------------------------------------------------------------------------------- /ch05b/db_config/peewee_connect.py: -------------------------------------------------------------------------------- 1 | from peewee import PostgresqlDatabase, _ConnectionState 2 | from contextvars import ContextVar 3 | 4 | db_state_default = {"closed": None, "conn": None, "ctx": None, "transactions": None} 5 | db_state = ContextVar("db_state", default=db_state_default.copy()) 6 | 7 | 8 | class PeeweeConnectionState(_ConnectionState): 9 | def __init__(self, **kwargs): 10 | super().__setattr__("_state", db_state) 11 | super().__init__(**kwargs) 12 | 13 | def __setattr__(self, name, value): 14 | self._state.get()[name] = value 15 | 16 | def __getattr__(self, name): 17 | return self._state.get()[name] 18 | 19 | db = PostgresqlDatabase( 20 | 'fcms2', 21 | user='postgres', 22 | password='admin2255', 23 | host='localhost', 24 | port=5433, 25 | ) 26 | 27 | db._state = PeeweeConnectionState() -------------------------------------------------------------------------------- /ch05b/db_config/sqlalchemy_async_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession 2 | from sqlalchemy.orm import declarative_base, sessionmaker 3 | 4 | DB_URL = "postgresql+asyncpg://postgres:admin2255@localhost:5433/fcms" 5 | engine = create_async_engine(DB_URL, future=True, echo=True) 6 | AsynSessionFactory = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession) 7 | Base = declarative_base() -------------------------------------------------------------------------------- /ch05b/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | from api import login, attendance, gym 4 | 5 | app = FastAPI() 6 | app.include_router(login.router, prefix='/ch05') 7 | app.include_router(attendance.router, prefix='/ch05') 8 | app.include_router(gym.router, prefix='/ch05') 9 | 10 | -------------------------------------------------------------------------------- /ch05b/models/requests/attendance.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class AttendanceMemberReq(BaseModel): 5 | id: int 6 | member_id: int 7 | timeout:str 8 | timein:str 9 | date_log:date -------------------------------------------------------------------------------- /ch05b/models/requests/gym.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class GymClassReq(BaseModel): 5 | 6 | id: int 7 | name: str 8 | member_id: int 9 | trainer_id: int 10 | approved : int 11 | 12 | 13 | -------------------------------------------------------------------------------- /ch05b/models/requests/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class LoginReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | date_approved:date 9 | user_type:int 10 | 11 | class Config: 12 | orm_mode = True 13 | 14 | -------------------------------------------------------------------------------- /ch05b/requirements.txt: -------------------------------------------------------------------------------- 1 | aiopg==1.3.4 2 | anyio==3.6.1 3 | async-timeout==4.0.2 4 | asyncpg==0.26.0 5 | click==8.1.3 6 | colorama==0.4.5 7 | fastapi==0.78.0 8 | greenlet==1.1.2 9 | h11==0.13.0 10 | idna==3.3 11 | peewee==3.15.1 12 | psycopg2-binary==2.9.3 13 | pydantic==1.9.1 14 | python-multipart==0.0.5 15 | six==1.16.0 16 | sniffio==1.2.0 17 | SQLAlchemy==1.4.39 18 | starlette==0.19.1 19 | typing_extensions==4.3.0 20 | uvicorn==0.18.2 21 | -------------------------------------------------------------------------------- /ch06/database/UML design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch06/database/UML design.png -------------------------------------------------------------------------------- /ch06/database/obrs_db.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch06/database/obrs_db.zip -------------------------------------------------------------------------------- /ch06/db_config/beanie_config.py: -------------------------------------------------------------------------------- 1 | 2 | from motor.motor_asyncio import AsyncIOMotorClient 3 | from beanie import init_beanie 4 | from models.data.beanie import Cart, Order, Receipt 5 | 6 | async def db_connect(): 7 | global client 8 | client = AsyncIOMotorClient(f"mongodb://localhost:27017/obrs") 9 | await init_beanie(client.obrs, document_models=[Cart, Order, Receipt]) 10 | 11 | async def db_disconnect(): 12 | client.close() -------------------------------------------------------------------------------- /ch06/db_config/mongoengine_config.py: -------------------------------------------------------------------------------- 1 | from mongoengine import connect 2 | 3 | def create_db(): 4 | global db 5 | db = connect(db="obrs", host="localhost", port=27017) 6 | 7 | def disconnect_db(): 8 | db.close() -------------------------------------------------------------------------------- /ch06/db_config/mongoframe_config.py: -------------------------------------------------------------------------------- 1 | from pymongo import MongoClient 2 | from mongoframes import Frame 3 | 4 | def create_db_client(): 5 | Frame._client = MongoClient('mongodb://localhost:27017/obrs') 6 | 7 | def disconnect_db_client(): 8 | Frame._client.close() 9 | -------------------------------------------------------------------------------- /ch06/db_config/motor_config.py: -------------------------------------------------------------------------------- 1 | from motor.motor_asyncio import AsyncIOMotorClient 2 | 3 | 4 | def create_async_db(): 5 | global client 6 | client = AsyncIOMotorClient(str("localhost:27017")) 7 | 8 | def create_db_collections(): 9 | db = client.obrs 10 | buyers = db["buyer"] 11 | users = db["login"] 12 | return {"users": users, "buyers": buyers} 13 | 14 | def close_async_db(): 15 | client.close() -------------------------------------------------------------------------------- /ch06/db_config/odmantic_config.py: -------------------------------------------------------------------------------- 1 | from odmantic import AIOEngine 2 | from motor.motor_asyncio import AsyncIOMotorClient 3 | 4 | def create_db_connection(): 5 | global client_od 6 | client_od = AsyncIOMotorClient(f"mongodb://localhost:27017/") 7 | 8 | def create_db_engine(): 9 | engine = AIOEngine(motor_client=client_od, database="obrs") 10 | return engine 11 | 12 | def close_db_connection(): 13 | client_od.close() 14 | -------------------------------------------------------------------------------- /ch06/db_config/pymongo_config.py: -------------------------------------------------------------------------------- 1 | from pymongo import MongoClient 2 | 3 | def create_db_collections(): 4 | client = MongoClient('mongodb://localhost:27017/') 5 | try: 6 | db = client.obrs 7 | buyers = db.buyer 8 | users = db.login 9 | yield {"users": users, "buyers": buyers} 10 | finally: 11 | client.close() 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch06/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import book, buyer, buyer_async, cart, receipt, order, login, profile, purchase, reference 3 | 4 | app = FastAPI() 5 | app.include_router(purchase.router, prefix="/ch06") 6 | app.include_router(buyer.router, prefix="/ch06") 7 | app.include_router(buyer_async.router, prefix="/ch06") 8 | app.include_router(receipt.router, prefix="/ch06") 9 | app.include_router(order.router, prefix="/ch06") 10 | app.include_router(cart.router, prefix="/ch06") 11 | app.include_router(login.router, prefix="/ch06") 12 | app.include_router(profile.router, prefix="/ch06") 13 | app.include_router(book.router, prefix="/ch06") 14 | app.include_router(reference.router, prefix="/ch06") -------------------------------------------------------------------------------- /ch06/models/data/mongoframe.py: -------------------------------------------------------------------------------- 1 | from mongoframes import Frame, SubFrame 2 | 3 | class Book(Frame): 4 | _fields = { 5 | 'id ', 6 | 'isbn', 7 | 'author', 8 | 'date_published', 9 | 'title', 10 | 'edition', 11 | 'price', 12 | 'category' 13 | } 14 | _collection = "book" 15 | 16 | 17 | class Category(SubFrame): 18 | 19 | _fields = { 20 | 'id', 21 | 'name', 22 | 'description', 23 | 'date_added' 24 | } 25 | 26 | _collection = "category" 27 | 28 | class Reference(Frame): 29 | 30 | _fields = { 31 | 'id', 32 | 'name', 33 | 'description', 34 | 'categories' 35 | } 36 | 37 | _collection = "reference" -------------------------------------------------------------------------------- /ch06/models/data/odmantic.py: -------------------------------------------------------------------------------- 1 | from odmantic import Model 2 | from bson import datetime 3 | 4 | class Purchase(Model): 5 | purchase_id: int 6 | buyer_id: int 7 | book_id: int 8 | items: int 9 | price: float 10 | date_purchased: datetime.datetime 11 | 12 | class Config: 13 | collection = "purchase" -------------------------------------------------------------------------------- /ch06/models/request/category.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Any, Optional 3 | from datetime import date 4 | 5 | 6 | class CategoryReq(BaseModel): 7 | id: int 8 | name: str 9 | description: str 10 | date_added: date 11 | 12 | class ReferenceReq(BaseModel): 13 | id: int 14 | name: str 15 | description: str 16 | date_added: date 17 | categories: List[Any] = list() 18 | 19 | class BookReq(BaseModel): 20 | id: int 21 | isbn: str 22 | author: str 23 | title: str 24 | edition: int 25 | date_published: date 26 | price: float 27 | category: Optional[CategoryReq] = None -------------------------------------------------------------------------------- /ch06/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List 3 | from datetime import date 4 | 5 | class LoginReq(BaseModel): 6 | id: int 7 | username: str 8 | password: str 9 | -------------------------------------------------------------------------------- /ch06/models/request/order.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List 3 | from datetime import date 4 | 5 | class OrderReq(BaseModel): 6 | id: int 7 | user_id: int 8 | date_ordered: date 9 | 10 | class ReceiptReq(BaseModel): 11 | id: int 12 | date_receipt: date 13 | total: float 14 | payment_mode: int 15 | order_id: int 16 | 17 | class CartReq(BaseModel): 18 | id: int 19 | book_id: int 20 | user_id: int 21 | qty: int 22 | date_carted: date 23 | discount: float -------------------------------------------------------------------------------- /ch06/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List 3 | from datetime import date 4 | 5 | class UserProfileReq(BaseModel): 6 | firstname: str 7 | lastname: str 8 | middlename: str 9 | position: str 10 | date_approved: date 11 | status: bool 12 | level: int 13 | login_id: int 14 | 15 | class BookForSaleReq(BaseModel): 16 | id:int 17 | isbn:str 18 | author:str 19 | date_published:date 20 | title:str 21 | edition:int 22 | price:float -------------------------------------------------------------------------------- /ch06/models/request/purchase.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List 3 | from datetime import date 4 | 5 | class PurchaseReq(BaseModel): 6 | purchase_id: int 7 | buyer_id: int 8 | book_id: int 9 | items: int 10 | price: float 11 | date_purchased: date 12 | 13 | -------------------------------------------------------------------------------- /ch06/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | beanie==1.11.6 3 | blinker==1.4 4 | click==8.1.3 5 | colorama==0.4.5 6 | Faker==13.15.0 7 | fastapi==0.78.0 8 | h11==0.13.0 9 | idna==3.3 10 | mongoengine==0.24.1 11 | MongoFrames==1.3.6 12 | motor==3.0.0 13 | multidict==6.0.2 14 | odmantic==0.5.0 15 | pydantic==1.9.1 16 | pymongo==4.1.1 17 | python-dateutil==2.8.2 18 | python-multipart==0.0.5 19 | six==1.16.0 20 | sniffio==1.2.0 21 | starlette==0.19.1 22 | toml==0.10.2 23 | typing_extensions==4.3.0 24 | uvicorn==0.18.2 25 | yarl==1.7.2 26 | -------------------------------------------------------------------------------- /ch07a/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07a/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login, profile, auction, bid 3 | 4 | app = FastAPI() 5 | 6 | app.include_router(admin.router, prefix="/ch07") 7 | app.include_router(login.router, prefix="/ch07") 8 | app.include_router(profile.router, prefix="/ch07") 9 | app.include_router(auction.router, prefix="/ch07") 10 | app.include_router(bid.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} 15 | -------------------------------------------------------------------------------- /ch07a/models/request/auctions.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class AuctionsReq(BaseModel): 6 | id:int 7 | name:str 8 | details:str 9 | type_id:int 10 | max_price:float 11 | min_price:float 12 | buyout_price:float 13 | created_date:date 14 | updated_date:date 15 | condition:str 16 | profile_id:int -------------------------------------------------------------------------------- /ch07a/models/request/bids.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | 5 | class BidsReq(BaseModel): 6 | id:int 7 | auction_id:int 8 | profile_id:int 9 | created_date:date 10 | updated_date:date 11 | price:float -------------------------------------------------------------------------------- /ch07a/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07a/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | id:int 6 | firstname:str 7 | lastname:str 8 | age:int 9 | membership_date : date 10 | member_type:str 11 | login_id:int 12 | status:int -------------------------------------------------------------------------------- /ch07a/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07a/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | class TokenData(BaseModel): 9 | username: Optional[str] = None -------------------------------------------------------------------------------- /ch07a/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: February 15, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07a/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | fastapi==0.78.0 5 | greenlet==1.1.2 6 | h11==0.13.0 7 | idna==3.3 8 | passlib==1.7.4 9 | psycopg2==2.9.3 10 | pydantic==1.9.1 11 | python-multipart==0.0.5 12 | six==1.16.0 13 | sniffio==1.2.0 14 | SQLAlchemy==1.4.39 15 | starlette==0.19.1 16 | typing_extensions==4.3.0 17 | uvicorn==0.18.2 18 | -------------------------------------------------------------------------------- /ch07a/security/secure.py: -------------------------------------------------------------------------------- 1 | from passlib.context import CryptContext 2 | from fastapi.security import HTTPBasicCredentials 3 | from fastapi.security import HTTPBasic 4 | 5 | from secrets import compare_digest 6 | from models.data.sqlalchemy_models import Login 7 | 8 | crypt_context = CryptContext(schemes=["sha256_crypt", "md5_crypt"]) 9 | 10 | http_basic = HTTPBasic() 11 | 12 | def get_password_hash(password): 13 | return crypt_context.hash(password) 14 | 15 | def verify_password(plain_password, hashed_password): 16 | return crypt_context.verify(plain_password, hashed_password) 17 | 18 | def authenticate(credentials: HTTPBasicCredentials, account:Login): 19 | try: 20 | is_username = compare_digest(credentials.username, account.username) 21 | is_password = compare_digest(credentials.password, account.username) 22 | verified_password = verify_password(credentials.password, account.passphrase) 23 | return (verified_password and is_username and is_password) 24 | except Exception as e: 25 | print(e) 26 | return False 27 | -------------------------------------------------------------------------------- /ch07b/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07b/generate_hash.py: -------------------------------------------------------------------------------- 1 | from base64 import urlsafe_b64encode 2 | 3 | h = urlsafe_b64encode(b"sjctrags:sjctrags") 4 | print(h) 5 | # c2pjdHJhZ3M6c2pjdHJhZ3M= -------------------------------------------------------------------------------- /ch07b/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login, profile, auction, bid 3 | 4 | app = FastAPI() 5 | 6 | app.include_router(admin.router, prefix="/ch07") 7 | app.include_router(login.router, prefix="/ch07") 8 | app.include_router(profile.router, prefix="/ch07") 9 | app.include_router(auction.router, prefix="/ch07") 10 | app.include_router(bid.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} 15 | 16 | 17 | # ch07b -------------------------------------------------------------------------------- /ch07b/models/request/auctions.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class AuctionsReq(BaseModel): 6 | id:int 7 | name:str 8 | details:str 9 | type_id:int 10 | max_price:float 11 | min_price:float 12 | buyout_price:float 13 | created_date:date 14 | updated_date:date 15 | condition:str 16 | profile_id:int -------------------------------------------------------------------------------- /ch07b/models/request/bids.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | 5 | class BidsReq(BaseModel): 6 | id:int 7 | auction_id:int 8 | profile_id:int 9 | created_date:date 10 | updated_date:date 11 | price:float -------------------------------------------------------------------------------- /ch07b/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07b/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | id:int 6 | firstname:str 7 | lastname:str 8 | age:int 9 | membership_date : date 10 | member_type:str 11 | login_id:int 12 | status:int -------------------------------------------------------------------------------- /ch07b/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07b/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | class TokenData(BaseModel): 9 | username: Optional[str] = None -------------------------------------------------------------------------------- /ch07b/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: February 15, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07b/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | fastapi==0.78.0 5 | greenlet==1.1.2 6 | h11==0.13.0 7 | idna==3.3 8 | passlib==1.7.4 9 | psycopg2==2.9.3 10 | pydantic==1.9.1 11 | python-multipart==0.0.5 12 | six==1.16.0 13 | sniffio==1.2.0 14 | SQLAlchemy==1.4.39 15 | starlette==0.19.1 16 | typing_extensions==4.3.0 17 | uvicorn==0.18.2 18 | -------------------------------------------------------------------------------- /ch07c/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07c/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login, profile, auction, bid 3 | 4 | app = FastAPI() 5 | 6 | app.include_router(admin.router, prefix="/ch07") 7 | app.include_router(login.router, prefix="/ch07") 8 | app.include_router(profile.router, prefix="/ch07") 9 | app.include_router(auction.router, prefix="/ch07") 10 | app.include_router(bid.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} 15 | 16 | 17 | #ch07c -------------------------------------------------------------------------------- /ch07c/models/request/auctions.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class AuctionsReq(BaseModel): 6 | id:int 7 | name:str 8 | details:str 9 | type_id:int 10 | max_price:float 11 | min_price:float 12 | buyout_price:float 13 | created_date:date 14 | updated_date:date 15 | condition:str 16 | profile_id:int -------------------------------------------------------------------------------- /ch07c/models/request/bids.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | 5 | class BidsReq(BaseModel): 6 | id:int 7 | auction_id:int 8 | profile_id:int 9 | created_date:date 10 | updated_date:date 11 | price:float -------------------------------------------------------------------------------- /ch07c/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07c/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | id:int 6 | firstname:str 7 | lastname:str 8 | age:int 9 | membership_date : date 10 | member_type:str 11 | login_id:int 12 | status:int -------------------------------------------------------------------------------- /ch07c/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07c/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | class TokenData(BaseModel): 9 | username: Optional[str] = None -------------------------------------------------------------------------------- /ch07c/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: February 15, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07c/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | fastapi==0.78.0 5 | greenlet==1.1.2 6 | h11==0.13.0 7 | idna==3.3 8 | passlib==1.7.4 9 | psycopg2==2.9.3 10 | pydantic==1.9.1 11 | python-multipart==0.0.5 12 | six==1.16.0 13 | sniffio==1.2.0 14 | SQLAlchemy==1.4.39 15 | starlette==0.19.1 16 | typing_extensions==4.3.0 17 | uvicorn==0.18.2 18 | -------------------------------------------------------------------------------- /ch07d/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07d/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login, profile, auction, bid 3 | 4 | app = FastAPI() 5 | 6 | app.include_router(admin.router, prefix="/ch07") 7 | app.include_router(login.router, prefix="/ch07") 8 | app.include_router(profile.router, prefix="/ch07") 9 | app.include_router(auction.router, prefix="/ch07") 10 | app.include_router(bid.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} 15 | 16 | 17 | # ch07c -------------------------------------------------------------------------------- /ch07d/models/request/auctions.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class AuctionsReq(BaseModel): 6 | id:int 7 | name:str 8 | details:str 9 | type_id:int 10 | max_price:float 11 | min_price:float 12 | buyout_price:float 13 | created_date:date 14 | updated_date:date 15 | condition:str 16 | profile_id:int -------------------------------------------------------------------------------- /ch07d/models/request/bids.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | 5 | class BidsReq(BaseModel): 6 | id:int 7 | auction_id:int 8 | profile_id:int 9 | created_date:date 10 | updated_date:date 11 | price:float -------------------------------------------------------------------------------- /ch07d/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07d/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | id:int 6 | firstname:str 7 | lastname:str 8 | age:int 9 | membership_date : date 10 | member_type:str 11 | login_id:int 12 | status:int -------------------------------------------------------------------------------- /ch07d/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07d/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | from pydantic.dataclasses import dataclass 4 | 5 | @dataclass 6 | class Token(): 7 | access_token: str 8 | token_type: str 9 | 10 | @dataclass 11 | class TokenData(): 12 | username: Optional[str] = None -------------------------------------------------------------------------------- /ch07d/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: February 15, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07d/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | ecdsa==0.18.0 5 | fastapi==0.78.0 6 | greenlet==1.1.2 7 | h11==0.13.0 8 | idna==3.3 9 | passlib==1.7.4 10 | psycopg2==2.9.3 11 | pyasn1==0.4.8 12 | pydantic==1.9.1 13 | python-jose==3.3.0 14 | python-multipart==0.0.5 15 | rsa==4.8 16 | six==1.16.0 17 | sniffio==1.2.0 18 | SQLAlchemy==1.4.39 19 | starlette==0.19.1 20 | typing_extensions==4.3.0 21 | uvicorn==0.18.2 22 | -------------------------------------------------------------------------------- /ch07e/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07e/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login, profile, auction, bid 3 | 4 | app = FastAPI() 5 | 6 | app.include_router(admin.router, prefix="/ch07") 7 | app.include_router(login.router, prefix="/ch07") 8 | app.include_router(profile.router, prefix="/ch07") 9 | app.include_router(auction.router, prefix="/ch07") 10 | app.include_router(bid.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} -------------------------------------------------------------------------------- /ch07e/models/request/auctions.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class AuctionsReq(BaseModel): 6 | id:int 7 | name:str 8 | details:str 9 | type_id:int 10 | max_price:float 11 | min_price:float 12 | buyout_price:float 13 | created_date:date 14 | updated_date:date 15 | condition:str 16 | profile_id:int -------------------------------------------------------------------------------- /ch07e/models/request/bids.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | 5 | class BidsReq(BaseModel): 6 | id:int 7 | auction_id:int 8 | profile_id:int 9 | created_date:date 10 | updated_date:date 11 | price:float -------------------------------------------------------------------------------- /ch07e/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07e/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | id:int 6 | firstname:str 7 | lastname:str 8 | age:int 9 | membership_date : date 10 | member_type:str 11 | login_id:int 12 | status:int -------------------------------------------------------------------------------- /ch07e/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07e/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | from pydantic.dataclasses import dataclass 3 | from dataclasses import field 4 | 5 | @dataclass 6 | class Token(): 7 | access_token: str 8 | token_type: str 9 | 10 | @dataclass 11 | class TokenData(): 12 | username: Optional[str] = None 13 | scopes: List[str] = field(default_factory=lambda: []) -------------------------------------------------------------------------------- /ch07e/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: February 15, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07e/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | ecdsa==0.18.0 5 | fastapi==0.78.0 6 | greenlet==1.1.2 7 | h11==0.13.0 8 | idna==3.3 9 | passlib==1.7.4 10 | psycopg2==2.9.3 11 | pyasn1==0.4.8 12 | pydantic==1.9.1 13 | python-jose==3.3.0 14 | python-multipart==0.0.5 15 | rsa==4.8 16 | six==1.16.0 17 | sniffio==1.2.0 18 | SQLAlchemy==1.4.39 19 | starlette==0.19.1 20 | typing_extensions==4.3.0 21 | uvicorn==0.18.2 22 | -------------------------------------------------------------------------------- /ch07f/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07f/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login, profile, auction, bid 3 | 4 | app = FastAPI() 5 | 6 | app.include_router(admin.router, prefix="/ch07") 7 | app.include_router(login.router, prefix="/ch07") 8 | app.include_router(profile.router, prefix="/ch07") 9 | app.include_router(auction.router, prefix="/ch07") 10 | app.include_router(bid.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} -------------------------------------------------------------------------------- /ch07f/models/request/auctions.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class AuctionsReq(BaseModel): 6 | id:int 7 | name:str 8 | details:str 9 | type_id:int 10 | max_price:float 11 | min_price:float 12 | buyout_price:float 13 | created_date:date 14 | updated_date:date 15 | condition:str 16 | profile_id:int -------------------------------------------------------------------------------- /ch07f/models/request/bids.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | 5 | class BidsReq(BaseModel): 6 | id:int 7 | auction_id:int 8 | profile_id:int 9 | created_date:date 10 | updated_date:date 11 | price:float -------------------------------------------------------------------------------- /ch07f/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07f/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | id:int 6 | firstname:str 7 | lastname:str 8 | age:int 9 | membership_date : date 10 | member_type:str 11 | login_id:int 12 | status:int -------------------------------------------------------------------------------- /ch07f/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07f/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | 9 | class TokenData(BaseModel): 10 | username: Optional[str] = None 11 | scopes: List[str] = [] -------------------------------------------------------------------------------- /ch07f/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: March 10, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07f/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | click==8.1.3 3 | colorama==0.4.5 4 | ecdsa==0.18.0 5 | fastapi==0.78.0 6 | greenlet==1.1.2 7 | h11==0.13.0 8 | idna==3.3 9 | passlib==1.7.4 10 | psycopg2==2.9.3 11 | pyasn1==0.4.8 12 | pydantic==1.9.1 13 | python-jose==3.3.0 14 | python-multipart==0.0.5 15 | rsa==4.8 16 | six==1.16.0 17 | sniffio==1.2.0 18 | SQLAlchemy==1.4.39 19 | starlette==0.19.1 20 | typing_extensions==4.3.0 21 | uvicorn==0.18.2 22 | -------------------------------------------------------------------------------- /ch07g/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07g/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.requests import Request 3 | from fastapi.responses import JSONResponse 4 | from api import admin, login 5 | from security.secure import AuthError 6 | 7 | app = FastAPI() 8 | 9 | app.include_router(admin.router, prefix="/ch07") 10 | app.include_router(login.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} 15 | 16 | @app.exception_handler(AuthError) 17 | def handle_auth_error(request: Request, ex: AuthError): 18 | return JSONResponse(status_code=ex.status_code, content=ex.error) 19 | -------------------------------------------------------------------------------- /ch07g/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class LoginReq(BaseModel): 4 | username: str 5 | password: str -------------------------------------------------------------------------------- /ch07g/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class SignupReq(BaseModel): 4 | id : int 5 | username: str 6 | password: str 7 | 8 | class Config: 9 | orm_mode = True -------------------------------------------------------------------------------- /ch07g/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | class TokenData(BaseModel): 9 | username: Optional[str] = None -------------------------------------------------------------------------------- /ch07g/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: March 15, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07g/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | certifi==2022.6.15 3 | charset-normalizer==2.1.0 4 | click==8.1.3 5 | colorama==0.4.5 6 | ecdsa==0.18.0 7 | fastapi==0.78.0 8 | greenlet==1.1.2 9 | h11==0.13.0 10 | idna==3.3 11 | passlib==1.7.4 12 | psycopg2==2.9.3 13 | pyasn1==0.4.8 14 | pydantic==1.9.1 15 | PyJWT==2.4.0 16 | python-jose==3.3.0 17 | python-multipart==0.0.5 18 | requests==2.28.1 19 | rsa==4.8 20 | six==1.16.0 21 | sniffio==1.2.0 22 | SQLAlchemy==1.4.39 23 | starlette==0.19.1 24 | typing_extensions==4.3.0 25 | urllib3==1.26.10 26 | uvicorn==0.18.2 27 | -------------------------------------------------------------------------------- /ch07h/app.env: -------------------------------------------------------------------------------- 1 | [Okta] 2 | OKTA_CLIENT_ID=0oa3tvejee5UPt7QZ5d7 3 | OKTA_CLIENT_SECRET=LA4WP8lACWKu4Ke9fReol0fNSUvxsxTvGLZdDS5- 4 | OKTA_ISSUER=https://dev-5180227.okta.com/oauth2/default 5 | OKTA_AUDIENCE=api://default 6 | ALGORITHMS = RS256 -------------------------------------------------------------------------------- /ch07h/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | from sqlalchemy import update, delete, insert 5 | 6 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 7 | 8 | engine = create_engine(DB_URL) 9 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 10 | 11 | Base = declarative_base() 12 | 13 | 14 | def sess_db(): 15 | db = SessionFactory() 16 | try: 17 | yield db 18 | finally: 19 | db.close() -------------------------------------------------------------------------------- /ch07h/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.requests import Request 3 | from fastapi.responses import JSONResponse 4 | from api import admin, login 5 | 6 | 7 | app = FastAPI() 8 | 9 | app.include_router(admin.router, prefix="/ch07") 10 | app.include_router(login.router, prefix="/ch07") 11 | 12 | @app.get("/index") 13 | def index(): 14 | return {"content": "welcome"} 15 | 16 | 17 | #ch07h -------------------------------------------------------------------------------- /ch07h/models/request/login.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | from pydantic import BaseModel 3 | 4 | 5 | class LoginReq(BaseModel): 6 | username: str 7 | password: str -------------------------------------------------------------------------------- /ch07h/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | from pydantic import BaseModel 3 | 4 | 5 | class SignupReq(BaseModel): 6 | id : int 7 | username: str 8 | password: str 9 | 10 | class Config: 11 | orm_mode = True -------------------------------------------------------------------------------- /ch07h/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | class TokenData(BaseModel): 9 | username: Optional[str] = None 10 | 11 | class Message(BaseModel): 12 | sent_from: str 13 | sent_to: str 14 | msg: str -------------------------------------------------------------------------------- /ch07h/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: April 3, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07h/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | certifi==2022.6.15 3 | charset-normalizer==2.1.0 4 | click==8.1.3 5 | colorama==0.4.5 6 | ecdsa==0.18.0 7 | fastapi==0.78.0 8 | greenlet==1.1.2 9 | h11==0.12.0 10 | httpcore==0.15.0 11 | httpx==0.23.0 12 | idna==3.3 13 | okta-jwt==1.3.5 14 | passlib==1.7.4 15 | psycopg2==2.9.3 16 | pyasn1==0.4.8 17 | pydantic==1.9.1 18 | PyJWT==2.4.0 19 | python-jose==3.3.0 20 | python-multipart==0.0.5 21 | requests==2.28.1 22 | rfc3986==1.5.0 23 | six==1.16.0 24 | sniffio==1.2.0 25 | SQLAlchemy==1.4.39 26 | starlette==0.19.1 27 | typing_extensions==4.3.0 28 | urllib3==1.26.10 29 | uvicorn==0.18.2 30 | -------------------------------------------------------------------------------- /ch07i/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07i/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07i/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07i/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | class TokenData(BaseModel): 9 | username: Optional[str] = None -------------------------------------------------------------------------------- /ch07i/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: April 3, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07i/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | certifi==2022.6.15 3 | cffi==1.15.1 4 | charset-normalizer==2.1.0 5 | click==8.1.3 6 | colorama==0.4.5 7 | cryptography==37.0.4 8 | fastapi==0.78.0 9 | greenlet==1.1.2 10 | h11==0.13.0 11 | idna==3.3 12 | passlib==1.7.4 13 | psycopg2==2.9.3 14 | pyasn1==0.4.8 15 | pycparser==2.21 16 | pydantic==1.9.1 17 | PyJWT==2.4.0 18 | python-multipart==0.0.5 19 | requests==2.28.1 20 | rsa==4.8 21 | six==1.16.0 22 | sniffio==1.2.0 23 | SQLAlchemy==1.4.39 24 | starlette==0.19.1 25 | typing_extensions==4.3.0 26 | urllib3==1.26.10 27 | uvicorn==0.18.2 28 | -------------------------------------------------------------------------------- /ch07j/db_config/sqlalchemy_connect.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DB_URL = "postgresql://postgres:admin2255@localhost:5433/soas" 6 | 7 | engine = create_engine(DB_URL) 8 | SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) 9 | 10 | Base = declarative_base() 11 | 12 | 13 | def sess_db(): 14 | db = SessionFactory() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /ch07j/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from api import admin, login 3 | 4 | from security.secure import UsernameAuthBackend 5 | from starlette.middleware import Middleware 6 | from starlette.middleware.authentication import AuthenticationMiddleware 7 | 8 | 9 | middleware = [Middleware(AuthenticationMiddleware, backend=UsernameAuthBackend("sjctrags"))] 10 | app = FastAPI(middleware=middleware) 11 | 12 | app.include_router(admin.router, prefix="/ch07") 13 | app.include_router(login.router, prefix="/ch07") 14 | 15 | @app.get("/index") 16 | def index(): 17 | return {"content": "welcome"} 18 | 19 | -------------------------------------------------------------------------------- /ch07j/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class LoginReq(BaseModel): 5 | username: str 6 | password: str -------------------------------------------------------------------------------- /ch07j/models/request/signup.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | 4 | class SignupReq(BaseModel): 5 | id : int 6 | username: str 7 | password: str 8 | 9 | class Config: 10 | orm_mode = True -------------------------------------------------------------------------------- /ch07j/models/request/tokens.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | from pydantic import BaseModel 3 | 4 | class Token(BaseModel): 5 | access_token: str 6 | token_type: str 7 | 8 | 9 | class TokenData(BaseModel): 10 | username: Optional[str] = None 11 | scopes: List[str] = [] -------------------------------------------------------------------------------- /ch07j/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Secured Online Auction System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: April 3, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is an auction system that accepts any products from auctioneers 10 | for bidding. The application should determine the highest price bid to sell a 11 | product. The prototype is secured using various approaches to securing 12 | FastAPI microservice applications. 13 | 14 | This application uses the FastAPI framework driven by Python 3.8. 15 | This application now involves data storage using PostgreSQL 13. 16 | The backup database schema is in the /database folder of the project. 17 | 18 | The requirements.txt will guide you with the dependencies. Just install by running: 19 | pip install -r requirements.txt 20 | -------------------------------------------------------------------------------- /ch07j/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | cffi==1.15.1 3 | click==8.1.3 4 | colorama==0.4.5 5 | cryptography==37.0.4 6 | ecdsa==0.18.0 7 | fastapi==0.78.0 8 | greenlet==1.1.2 9 | h11==0.13.0 10 | idna==3.3 11 | passlib==1.7.4 12 | psycopg2==2.9.3 13 | pyasn1==0.4.8 14 | pycparser==2.21 15 | pydantic==1.9.1 16 | PyJWT==2.4.0 17 | python-jose==3.3.0 18 | python-multipart==0.0.5 19 | rsa==4.8 20 | six==1.16.0 21 | sniffio==1.2.0 22 | SQLAlchemy==1.4.39 23 | starlette==0.19.1 24 | typing_extensions==4.3.0 25 | uvicorn==0.18.2 26 | -------------------------------------------------------------------------------- /ch08/api/content.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Request 2 | from fastapi.responses import JSONResponse 3 | from models.request.content import ContentReq 4 | from models.data.nsms import Content, Publication 5 | from repository.content import ContentRepository 6 | from config.db.gino_db import db 7 | 8 | 9 | router = APIRouter() 10 | 11 | 12 | @router.post("/content/add") 13 | async def add_content(req: ContentReq): 14 | content_dict = req.dict(exclude_unset=True) 15 | repo = ContentRepository() 16 | result = await repo.insert_content(content_dict) 17 | if result == True: 18 | return req 19 | else: 20 | return JSONResponse(content={'message':'update trainer profile problem encountered'}, status_code=500) 21 | 22 | @router.get("/content/list") 23 | async def list_content(): 24 | repo = ContentRepository() 25 | result = await repo.get_all_content() 26 | return result -------------------------------------------------------------------------------- /ch08/api/publication.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends 2 | from fastapi.responses import JSONResponse 3 | from models.request.publication import PublicationReq 4 | from models.data.nsms import Publication, Messenger 5 | from repository.publication import PublicationRepository 6 | from config.db.gino_db import db 7 | 8 | 9 | 10 | 11 | 12 | router = APIRouter() 13 | 14 | 15 | @router.post("/publication/add") 16 | async def add_publication(req: PublicationReq): 17 | publication_dict = req.dict(exclude_unset=True) 18 | repo = PublicationRepository() 19 | result = await repo.insert_publication(publication_dict) 20 | if result == True: 21 | return req 22 | else: 23 | return JSONResponse(content={'message':'update trainer profile problem encountered'}, status_code=500) 24 | 25 | @router.get("/publication/list") 26 | async def list_publication(): 27 | repo = PublicationRepository() 28 | result = await repo.get_all_publication() 29 | return result -------------------------------------------------------------------------------- /ch08/api/vendor.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends 2 | from fastapi.responses import JSONResponse 3 | from models.request.vendor import VendorReq 4 | from models.data.nsms import Vendor, Login 5 | from repository.vendor import VendorRepository 6 | from config.db.gino_db import db 7 | 8 | 9 | 10 | 11 | 12 | router = APIRouter() 13 | 14 | 15 | @router.post("/vendor/add") 16 | async def add_vendor(req: VendorReq): 17 | vendor_dict = req.dict(exclude_unset=True) 18 | repo = VendorRepository() 19 | result = await repo.insert_vendor(vendor_dict) 20 | if result == True: 21 | return req 22 | else: 23 | return JSONResponse(content={'message':'update trainer profile problem encountered'}, status_code=500) 24 | 25 | @router.get("/vendor/list") 26 | async def list_vendor(): 27 | repo = VendorRepository() 28 | result = await repo.get_all_vendor() 29 | return result -------------------------------------------------------------------------------- /ch08/celery_test.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | 3 | original_callback = uvicorn.main.callback 4 | 5 | def callback(**kwargs): 6 | from celery.contrib.testing.worker import start_worker 7 | import services.billing 8 | 9 | with start_worker(services.billing.celery, perform_ping_check=False, loglevel="info"): 10 | original_callback(**kwargs) 11 | 12 | uvicorn.main.callback = callback 13 | 14 | 15 | if __name__ == "__main__": 16 | uvicorn.main() -------------------------------------------------------------------------------- /ch08/config/db/gino_db.py: -------------------------------------------------------------------------------- 1 | from gino import Gino 2 | 3 | db = Gino() -------------------------------------------------------------------------------- /ch08/data/billing-2022-03-16.csv: -------------------------------------------------------------------------------- 1 | 2022-03-16;Manila Bulletin;MB-13456;800000.0;10002022-03-16; 2 | 3 | 2022-03-16;Manila Bulletin;MB-13456;800000.0;1000 4 | -------------------------------------------------------------------------------- /ch08/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | from api import login, admin, vendor, customer, billing, messenger, publication, content, sales, subscription 4 | from config.db.gino_db import db 5 | app = FastAPI() 6 | 7 | @app.on_event("startup") 8 | async def initialize(): 9 | engine = await db.set_bind("postgresql+asyncpg://postgres:admin2255@localhost:5433/nsms") 10 | 11 | @app.on_event("shutdown") 12 | async def destroy(): 13 | engine, db.bind = db.bind, None 14 | await engine.close() 15 | 16 | app.include_router(login.router, prefix='/ch08') 17 | app.include_router(admin.router, prefix='/ch08') 18 | app.include_router(vendor.router, prefix='/ch08') 19 | app.include_router(customer.router, prefix='/ch08') 20 | app.include_router(billing.router, prefix='/ch08') 21 | app.include_router(messenger.router, prefix='/ch08') 22 | app.include_router(publication.router, prefix='/ch08') 23 | app.include_router(content.router, prefix='/ch08') 24 | app.include_router(sales.router, prefix='/ch08') 25 | app.include_router(subscription.router, prefix='/ch08') 26 | 27 | 28 | -------------------------------------------------------------------------------- /ch08/models/request/admin.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from typing import List, Dict 4 | from datetime import date 5 | 6 | class AdminReq(BaseModel): 7 | 8 | id: int 9 | firstname: str 10 | lastname: str 11 | age: int 12 | date_started: date 13 | status: int 14 | login_id: int 15 | birthday: date -------------------------------------------------------------------------------- /ch08/models/request/billing.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from datetime import date 4 | 5 | class BillingReq(BaseModel): 6 | id: int 7 | payable: float 8 | approved_by: str 9 | date_approved: date 10 | date_billed: date 11 | received_by: str 12 | date_received: date 13 | total_issues: int 14 | vendor_id: int 15 | admin_id: int -------------------------------------------------------------------------------- /ch08/models/request/content.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from datetime import date 4 | 5 | class ContentReq(BaseModel): 6 | id: int 7 | publication_id: int 8 | headline: str 9 | content: str 10 | content_type: str 11 | date_published: date -------------------------------------------------------------------------------- /ch08/models/request/customer.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from typing import List, Dict 4 | from datetime import date 5 | 6 | class CustomerReq(BaseModel): 7 | id: int 8 | firstname: str 9 | lastname: str 10 | age: int 11 | birthday: date 12 | date_subscribed: date 13 | status: int 14 | subscription_type: int 15 | login_id: int 16 | -------------------------------------------------------------------------------- /ch08/models/request/login.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | 4 | class LoginReq(BaseModel): 5 | id: int 6 | username: str 7 | password: str 8 | user_type: int 9 | 10 | -------------------------------------------------------------------------------- /ch08/models/request/messenger.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from datetime import date 4 | 5 | 6 | class MessengerReq(BaseModel): 7 | id: int 8 | firstname: str 9 | lastname: str 10 | salary: float 11 | date_employed: date 12 | status: int 13 | vendor_id: int 14 | -------------------------------------------------------------------------------- /ch08/models/request/publication.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from typing import List, Dict 4 | from datetime import date 5 | 6 | class PublicationReq(BaseModel): 7 | id: int 8 | name: str 9 | type: str 10 | vendor_id: int 11 | messenger_id: int -------------------------------------------------------------------------------- /ch08/models/request/sales.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from datetime import date 4 | 5 | class SalesReq(BaseModel): 6 | id: int 7 | publication_id: int 8 | copies_issued: int 9 | copies_sold: int 10 | date_issued: date 11 | revenue: float 12 | profit: float 13 | -------------------------------------------------------------------------------- /ch08/models/request/subscription.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from datetime import date 4 | 5 | 6 | class SubscriptionReq(BaseModel): 7 | id: int 8 | customer_id: int 9 | branch: str 10 | price: float 11 | qty: int 12 | date_purchased: date -------------------------------------------------------------------------------- /ch08/models/request/vendor.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from datetime import date 4 | 5 | class VendorReq(BaseModel): 6 | id: int 7 | rep_firstname: str 8 | rep_lastname: str 9 | rep_id: str 10 | rep_date_employed: date 11 | account_name: str 12 | account_number: str 13 | date_consigned: date 14 | login_id: int -------------------------------------------------------------------------------- /ch08/requirements.txt: -------------------------------------------------------------------------------- 1 | asyncpg==0.26.0 2 | distlib==0.3.6 3 | filelock==3.8.0 4 | gino==1.0.1 5 | greenlet==1.1.3 6 | numpy==1.23.2 7 | platformdirs==2.5.2 8 | SQLAlchemy==1.3.24 9 | virtualenv==20.16.3 10 | -------------------------------------------------------------------------------- /ch08/services/login.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from models.data.nsms import Login 3 | 4 | 5 | @asyncio.coroutine 6 | def build_user_list(query_list): 7 | user_list = [] 8 | for record in query_list: 9 | yield from asyncio.sleep(2) 10 | user_list.append(" ".join([str(record.id), record.username, record.password])) 11 | return user_list 12 | 13 | 14 | 15 | async def count_login(query_list): 16 | await asyncio.sleep(2) 17 | return len(query_list) 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch09/api/route_decrypt.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Depends, Request 2 | from models.request.secured_messages import EncLoginReq, EncRestaurantReq 3 | from util.auth_session import get_current_user 4 | from cryptography.fernet import Fernet 5 | from passlib.context import CryptContext 6 | from util.custom_routes import DecryptContentRoute 7 | 8 | router = APIRouter() 9 | router.route_class=DecryptContentRoute 10 | 11 | key = Fernet.generate_key() 12 | pwd_context = CryptContext( 13 | schemes=["pbkdf2_sha256"], 14 | default="pbkdf2_sha256", 15 | pbkdf2_sha256__default_rounds=30000 16 | ) 17 | 18 | @router.post("/login/decrypt/details") 19 | async def send_decrypt_login(enc_data: EncLoginReq, req:Request, user: str = Depends(get_current_user)): 20 | return {"data" : req.state.dec_data} 21 | 22 | @router.post("/restaurant/decrypt/details") 23 | async def send_decrypt_login(enc_data: EncRestaurantReq, req:Request, user: str = Depends(get_current_user)): 24 | return {"data" : req.state.dec_data} -------------------------------------------------------------------------------- /ch09/api/route_transform.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter , Form, Depends, File, UploadFile 2 | from util.custom_routes import FileStreamRoute 3 | from util.auth_session import get_current_user 4 | from typing import Optional 5 | 6 | router = APIRouter() 7 | router.route_class = FileStreamRoute 8 | 9 | @router.post("/files/") 10 | async def create_file(file: Optional[bytes] = File(...), user: str = Depends(get_current_user)): 11 | 12 | return {"file_size": len(file)} 13 | 14 | 15 | @router.post("/files/upload") 16 | async def create_file_2(file: Optional[UploadFile] = File(...) , user: str = Depends(get_current_user)): 17 | print(file.content_type) 18 | fs = await file.read() 19 | return {"file_size": len(fs)} 20 | 21 | -------------------------------------------------------------------------------- /ch09/config/db.py: -------------------------------------------------------------------------------- 1 | from odmantic import AIOEngine 2 | from motor.motor_asyncio import AsyncIOMotorClient 3 | 4 | def create_db_connection(): 5 | global client_od 6 | client_od = AsyncIOMotorClient(f"mongodb://localhost:27017/") 7 | 8 | def create_db_engine(): 9 | engine = AIOEngine(motor_client=client_od, database="orrs") 10 | return engine 11 | 12 | def close_db_connection(): 13 | client_od.close() -------------------------------------------------------------------------------- /ch09/database/orrs_db.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch09/database/orrs_db.zip -------------------------------------------------------------------------------- /ch09/files/file.txt: -------------------------------------------------------------------------------- 1 | ggfdgdfgdg -------------------------------------------------------------------------------- /ch09/files/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch09/files/logo.jpg -------------------------------------------------------------------------------- /ch09/files/questions.txt: -------------------------------------------------------------------------------- 1 | What is your favorite menu? 2 | How often do you eat here for dinner? 3 | How often do you eat here for breakfast? 4 | How often do you eat here for lunch? 5 | -------------------------------------------------------------------------------- /ch09/files/sample.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch09/files/sample.mp4 -------------------------------------------------------------------------------- /ch09/models/data/ratings_enum.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | class FoodRatingScale(int, Enum): 4 | FIVE_STAR = 5 5 | FOUR_STAR = 4 6 | THREE_STAR = 3 7 | TWO_STAR = 2 8 | ONE_STAR = 1 9 | 10 | class AmbianceRatingScale(int, Enum): 11 | STRONGLY_AGREE = 7 12 | AGREE = 6 13 | SOMEWHAT_AGREE = 5 14 | FINE = 4 15 | SOMEWHAT_DISAGREE = 3 16 | DISAGREE = 2 17 | STRONGLY_DISAGREE = 1 18 | 19 | -------------------------------------------------------------------------------- /ch09/models/documentation/__pycache__/response.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch09/models/documentation/__pycache__/response.cpython-38.pyc -------------------------------------------------------------------------------- /ch09/models/documentation/response.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | 3 | class Error500Model(BaseModel): 4 | message: str = "Video file is invalid." -------------------------------------------------------------------------------- /ch09/models/request/ambiance_rate.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | from models.data.ratings_enum import AmbianceRatingScale 4 | 5 | class AmbianceRateReq(BaseModel): 6 | question_id: int 7 | rate: AmbianceRatingScale 8 | date_rated: date 9 | profile_id: int -------------------------------------------------------------------------------- /ch09/models/request/feedback.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class FeedbackReq(BaseModel): 5 | message: str 6 | date_rated: date 7 | profile_id: int -------------------------------------------------------------------------------- /ch09/models/request/food_rate.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | from models.data.ratings_enum import FoodRatingScale 4 | 5 | class FoodRateReq(BaseModel): 6 | rate: FoodRatingScale 7 | date_rated: date 8 | profile_id: int -------------------------------------------------------------------------------- /ch09/models/request/keyword.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | 4 | class KeywordReq(BaseModel): 5 | word: str 6 | weight: int -------------------------------------------------------------------------------- /ch09/models/request/login.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | 4 | class LoginReq(BaseModel): 5 | login_id: int 6 | username: str 7 | password: str -------------------------------------------------------------------------------- /ch09/models/request/profile.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class ProfileReq(BaseModel): 5 | firstname: str 6 | lastname:str 7 | middlename:str 8 | date_signed: date 9 | age: int 10 | date_signed: date 11 | occupation: str 12 | birthday: date 13 | address: str 14 | 15 | -------------------------------------------------------------------------------- /ch09/models/request/question.py: -------------------------------------------------------------------------------- 1 | 2 | from pydantic import BaseModel 3 | from datetime import date 4 | 5 | class QuestionReq(BaseModel): 6 | question_id: int 7 | statement: str 8 | date_added: date 9 | profile_id: int 10 | -------------------------------------------------------------------------------- /ch09/models/request/restaurant.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | from typing import Optional 4 | 5 | class RestaurantReq(BaseModel): 6 | restaurant_id: int 7 | name: str 8 | branch: Optional[str] = None 9 | address: str 10 | province: str 11 | date_signed: date 12 | city: str 13 | country: str 14 | zipcode: int 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch09/models/request/secured_messages.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class EncLoginReq(BaseModel): 5 | enc_login: str 6 | key: str 7 | 8 | 9 | class EncRestaurantReq(BaseModel): 10 | enc_login: str 11 | key: str -------------------------------------------------------------------------------- /ch09/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Online Restaurant Review System 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: May 25, 2022 6 | 7 | =========================== Description ==================================== 8 | 9 | This prototype is a feedback and rating system designed for various restaurants. 10 | Users are required to answer survey questions regarding the restaurant's ambiance, 11 | menu, and hospitality. Aside from survey systems, the application can provide a 12 | nominal and numerical approach to the rating system. Overall, the prototype can 13 | be a foundation for a scalable survey system. 14 | 15 | This application uses the FastAPI framework driven by Python 3.8. 16 | This application now involves data storage using MongoDb 5.x. 17 | The backup database schema is in the /database folder of the project. 18 | 19 | The requirements.txt will guide you with the dependencies. Just install by running: 20 | pip install -r requirements.txt 21 | 22 | -------------------------------------------------------------------------------- /ch09/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% block content %} 17 | {% endblock content %} 18 | 19 | 20 | -------------------------------------------------------------------------------- /ch09/templates/page.html: -------------------------------------------------------------------------------- 1 |This is a Boostrap 4 table applied to JinjaTemplate.
7 |Login ID | 11 |Username | 12 |Password | 13 |Passphrase | 14 |
---|---|---|---|
{{ login.login_id}} | 20 |{{ login.username}} | 21 |{{ login.password}} | 22 |{{ login.passphrase}} | 23 |