├── 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 |

2 | Welcome to FastAPI Starter. 3 |

4 | {{data.page}} -------------------------------------------------------------------------------- /ch09/templates/upload_file.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block content %} 4 |
5 |

Upload Logo (PNG or PNG)

6 |
7 |
8 | 9 | 10 |
11 | 12 |
13 |
14 | {% endblock %} -------------------------------------------------------------------------------- /ch09/templates/users.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block content %} 4 |
5 |

List of users

6 |

This is a Boostrap 4 table applied to JinjaTemplate.

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for login in data %} 18 | 19 | 20 | 21 | 22 | 23 | 24 | {% endfor%} 25 | 26 |
Login IDUsernamePasswordPassphrase
{{ login.login_id}}{{ login.username}}{{ login.password}}{{ login.passphrase}}
27 |
28 | {% endblock %} -------------------------------------------------------------------------------- /ch09/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch09/test/__init__.py -------------------------------------------------------------------------------- /ch09/test/test_login.py: -------------------------------------------------------------------------------- 1 | from fastapi.testclient import TestClient 2 | from models.data.orrs import Login 3 | from main import app 4 | 5 | from util.auth_session import get_current_user 6 | from config.db import create_db_engine 7 | from odmantic import AIOEngine 8 | from motor.motor_asyncio import AsyncIOMotorClient 9 | 10 | client = TestClient(app) 11 | 12 | def db_connect(): 13 | client_od = AsyncIOMotorClient(f"mongodb://localhost:27017/") 14 | engine = AIOEngine(motor_client=client_od, database="orrs_test") 15 | return engine 16 | 17 | async def get_user(): 18 | return Login(**{"username": "sjctrags", "login_id": 101, "password":"sjctrags", "passphrase": None, "profile": None}) 19 | 20 | app.dependency_overrides[get_current_user] = get_user 21 | app.dependency_overrides[create_db_engine] = db_connect 22 | 23 | def test_list_login(): 24 | response = client.get("/ch09/login/list/all") 25 | assert response.status_code == 201 26 | -------------------------------------------------------------------------------- /ch09/test/test_restaurants.py: -------------------------------------------------------------------------------- 1 | from fastapi.testclient import TestClient 2 | 3 | from api import restaurant 4 | 5 | client = TestClient(restaurant.router) 6 | 7 | def test_restaurant_index(): 8 | response = client.get("/restaurant/index") 9 | assert response.status_code == 200 10 | assert response.text == "The Restaurants" 11 | -------------------------------------------------------------------------------- /ch09/test/test_route_extract.py: -------------------------------------------------------------------------------- 1 | from fastapi.testclient import TestClient 2 | from models.data.orrs import Login 3 | from main import app 4 | 5 | from util.auth_session import get_current_user 6 | 7 | client = TestClient(app) 8 | 9 | async def get_user(): 10 | return Login(**{"username": "sjctrags", "login_id": 101, "password":"sjctrags", "passphrase": None, "profile": None}) 11 | 12 | app.dependency_overrides[get_current_user] = get_user 13 | 14 | def test_rating_top_three(): 15 | response = client.post("/ch09/rating/top/three", json={ 16 | "rate1": 10.0, 17 | "rate2": 20.0 , 18 | "rate3": 30.0 19 | 20 | }) 21 | assert response.status_code == 200 22 | assert response.json() == { "stats": { 23 | "sum": 60.0, 24 | "average": 20.0 25 | } 26 | } -------------------------------------------------------------------------------- /ch09/util/json_date.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, date 2 | 3 | def json_datetime_serializer(obj): 4 | if isinstance(obj, (datetime, date)): 5 | return obj.strftime('%Y-%m-%dT%H:%M:%S.%f') 6 | raise TypeError ("The type %s not serializable." % type(obj)) -------------------------------------------------------------------------------- /ch10-mongo/config/pccs.py: -------------------------------------------------------------------------------- 1 | 2 | from motor.motor_asyncio import AsyncIOMotorClient 3 | from beanie import init_beanie 4 | from models.data.pccs_beanie import Login, Profile 5 | 6 | async def db_connect(): 7 | global client 8 | client = AsyncIOMotorClient(f"mongodb://localhost:27017/pccs") 9 | await init_beanie(client.pccs, document_models=[Login, Profile]) 10 | 11 | 12 | async def db_close(): 13 | client.close() -------------------------------------------------------------------------------- /ch10-mongo/config/pcss_neo4j.py: -------------------------------------------------------------------------------- 1 | from neo4j import GraphDatabase 2 | 3 | uri = "bolt://127.0.0.1:7687" 4 | driver = GraphDatabase.driver(uri, auth=("neo4j", "admin2255")) -------------------------------------------------------------------------------- /ch10-mongo/database/pccs_db.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/database/pccs_db.zip -------------------------------------------------------------------------------- /ch10-mongo/files/survey.csv: -------------------------------------------------------------------------------- 1 | ,Questions,Answers 2 | 0,q1,20 3 | 1,q2,30 4 | 2,q3,40 5 | -------------------------------------------------------------------------------- /ch10-mongo/files/survey.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/files/survey.xlsx -------------------------------------------------------------------------------- /ch10-mongo/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | from fastapi import FastAPI 4 | from starlette_graphene3 import GraphQLApp, make_graphiql_handler, make_playground_handler 5 | from config.pccs import db_connect, db_close 6 | 7 | from api import survey_graphene_login, survey_graphene_profile, survey_neo4j, survey_workflow 8 | 9 | app = FastAPI() 10 | app.include_router(survey_neo4j.router, prefix="/ch10") 11 | app.include_router(survey_workflow.router, prefix="/ch10") 12 | app.mount("/ch10/graphql/login", GraphQLApp(survey_graphene_login.schema, on_get=make_playground_handler()) ) 13 | app.mount("/ch10/graphql/profile", GraphQLApp(survey_graphene_profile.schema, on_get=make_playground_handler()) ) 14 | 15 | @app.on_event("startup") 16 | async def initialize(): 17 | await db_connect() 18 | 19 | @app.on_event("shutdown") 20 | async def destroy(): 21 | await db_close() 22 | 23 | -------------------------------------------------------------------------------- /ch10-mongo/models/data/__pycache__/pccs.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/models/data/__pycache__/pccs.cpython-38.pyc -------------------------------------------------------------------------------- /ch10-mongo/models/data/__pycache__/pccs_beanie.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/models/data/__pycache__/pccs_beanie.cpython-38.pyc -------------------------------------------------------------------------------- /ch10-mongo/models/data/__pycache__/pccs_graphql.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/models/data/__pycache__/pccs_graphql.cpython-38.pyc -------------------------------------------------------------------------------- /ch10-mongo/models/request/__pycache__/pccs_general.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/models/request/__pycache__/pccs_general.cpython-38.pyc -------------------------------------------------------------------------------- /ch10-mongo/models/request/__pycache__/pccs_neo4j.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/models/request/__pycache__/pccs_neo4j.cpython-38.pyc -------------------------------------------------------------------------------- /ch10-mongo/models/request/__pycache__/surveyor.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-mongo/models/request/__pycache__/surveyor.cpython-38.pyc -------------------------------------------------------------------------------- /ch10-mongo/models/request/pccs_general.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | from typing import Dict 4 | 5 | class SurveyDataResult(BaseModel): 6 | results: Dict[str, int] 7 | -------------------------------------------------------------------------------- /ch10-mongo/models/request/pccs_neo4j.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from datetime import date 3 | 4 | class LocationReq(BaseModel): 5 | name: str 6 | city: str 7 | state: str 8 | country: str 9 | 10 | class ProfileReq(BaseModel): 11 | name: str 12 | fname: str 13 | lname: str 14 | age: int 15 | position: str 16 | official_id: int 17 | date_employed : date 18 | 19 | class RespondentReq(BaseModel): 20 | name: str 21 | fname: str 22 | lname: str 23 | age: int 24 | birthday: date 25 | gender: str 26 | salary_estimate: float 27 | marital: bool 28 | 29 | class LinkAdminLoc(BaseModel): 30 | date_assigned : date 31 | duration: int 32 | 33 | class LinkRespondentLoc(BaseModel): 34 | address: str 35 | tax_id: int 36 | 37 | class LinkAdminRespondent(BaseModel): 38 | survey_id: int 39 | -------------------------------------------------------------------------------- /ch10-relational/README.md: -------------------------------------------------------------------------------- 1 | # piccolo_project 2 | 3 | ## Setup 4 | 5 | ### Install requirements 6 | 7 | ```bash 8 | pip install -r requirements.txt 9 | ``` 10 | 11 | ### Getting started guide 12 | 13 | ```bash 14 | python main.py 15 | ``` 16 | 17 | ### Running tests 18 | 19 | ```bash 20 | piccolo tester run 21 | ``` -------------------------------------------------------------------------------- /ch10-relational/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from piccolo.utils.warnings import colored_warning 4 | 5 | 6 | def pytest_configure(*args): 7 | if os.environ.get("PICCOLO_TEST_RUNNER") != "True": 8 | colored_warning( 9 | "\n\n" 10 | "We recommend running Piccolo tests using the " 11 | "`piccolo tester run` command, which wraps Pytest, and makes " 12 | "sure the test database is being used. " 13 | "To stop this warning, modify conftest.py." 14 | "\n\n" 15 | ) 16 | sys.exit(1) 17 | -------------------------------------------------------------------------------- /ch10-relational/countries.csv: -------------------------------------------------------------------------------- 1 | ID,First Name,Last Name,Age,Gender,Married? 2 | 3,Juan,Luna,32,1990-11-10,M,3,10,10000.0,Anzons Plaza,Tondo,12,4,PUP,False,0 3 | 4,Zeta,Ngo,30,1992-09-01,F,6,20,40000.0,LNHS,113 Real St.,13,6,Eastern Visayas State College,True,5 4 | 5,Jim,Chu,40,1982-05-11,M,6,13,60000.0,HSBC,Bangkal St.,15,6,UP Diliman,True,4 5 | 6,Larry,Santos,33,1991-03-22,M,8,16,55000.0,Makati Science High School,6754 Poblacion,15,7,TIP,False,1 6 | 7,Gene,Chua,23,1999-06-20,F,5,7,9600.0,Makati Science High School,Sampaloc,12,3,Soro-Soro High School,True,7 7 | 8,Larson,Alcala,55,1969-02-10,M,4,30,22600.0,NAPOLCOM,Pandacan,12,4,Pandacan Colleges,True,4 8 | 9,Stella,Marquez,45,1977-07-05,F,9,32,82600.0,DOST,123 Pioneer St,1,7,Up Diliman,True,3 9 | 10,John,Cruz,39,1983-10-15,M,5,23,8600.0,Zeus Merchandize,Soro Soro Ilaya,3,3,Mababang Paaralan ng Tibag,False,6 10 | 11,Liza,Muring,38,1984-08-28,F,11,26,33000.0,Alipay Bistro,178 Vietnam Village,11,6,Palawan College,True,2 11 | 12,Samuel,Relli,34,1988-04-27,M,10,11,89000.0,The Survey Inc,Little Baguio,9,8,UPLB,True,3 12 | -------------------------------------------------------------------------------- /ch10-relational/data.json: -------------------------------------------------------------------------------- 1 | {"columns":[0,1,2],"index":[0,1],"data":[[1,2,3],[4,5,6]]} -------------------------------------------------------------------------------- /ch10-relational/files/sample.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-relational/files/sample.csv -------------------------------------------------------------------------------- /ch10-relational/main.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | 3 | import uvicorn 4 | 5 | uvicorn.run("app:app", port=8002, reload=True) 6 | -------------------------------------------------------------------------------- /ch10-relational/piccolo_conf.py: -------------------------------------------------------------------------------- 1 | from piccolo.engine.postgres import PostgresEngine 2 | 3 | from piccolo.conf.apps import AppRegistry 4 | 5 | 6 | DB = PostgresEngine( 7 | config={ 8 | "database": "pccs", 9 | "user": "postgres", 10 | "password": "admin2255", 11 | "host": "localhost", 12 | "port": 5433, 13 | } 14 | ) 15 | 16 | APP_REGISTRY = AppRegistry( 17 | apps=["survey.piccolo_app", "piccolo_admin.piccolo_app"] 18 | ) 19 | -------------------------------------------------------------------------------- /ch10-relational/piccolo_conf_test.py: -------------------------------------------------------------------------------- 1 | from piccolo_conf import * # noqa 2 | 3 | 4 | DB = PostgresEngine( 5 | config={ 6 | "database": "piccolo_project_test", 7 | "user": "postgres", 8 | "password": "", 9 | "host": "localhost", 10 | "port": 5432, 11 | } 12 | ) 13 | -------------------------------------------------------------------------------- /ch10-relational/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-relational/static/favicon.ico -------------------------------------------------------------------------------- /ch10-relational/survey/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-relational/survey/__init__.py -------------------------------------------------------------------------------- /ch10-relational/survey/api/graphql.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | from piccolo_api.crud.endpoints import PiccoloCRUD 3 | from piccolo_api.fastapi.endpoints import FastAPIWrapper 4 | 5 | from survey.tables import Login, Profile 6 | 7 | router = APIRouter() 8 | 9 | FastAPIWrapper( 10 | "/login/", 11 | router, 12 | PiccoloCRUD(Login, read_only=False), 13 | ) 14 | 15 | FastAPIWrapper( 16 | "/profile/", 17 | router, 18 | PiccoloCRUD(Profile, read_only=False), 19 | ) -------------------------------------------------------------------------------- /ch10-relational/survey/piccolo_app.py: -------------------------------------------------------------------------------- 1 | """ 2 | Import all of the Tables subclasses in your app here, and register them with 3 | the APP_CONFIG. 4 | """ 5 | 6 | import os 7 | 8 | from piccolo.conf.apps import AppConfig 9 | from survey.tables import Answers, Education, Question, Profile, Login, Location, Occupation, Respondent, Choices 10 | 11 | CURRENT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) 12 | 13 | 14 | APP_CONFIG = AppConfig( 15 | app_name="survey", 16 | migrations_folder_path=os.path.join( 17 | CURRENT_DIRECTORY, "piccolo_migrations" 18 | ), 19 | table_classes=[Answers, Education, Question, Choices, Profile, Login, Location, 20 | Occupation, Respondent], 21 | migration_dependencies=[], 22 | commands=[], 23 | ) 24 | -------------------------------------------------------------------------------- /ch10-relational/survey/piccolo_migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch10-relational/survey/piccolo_migrations/__init__.py -------------------------------------------------------------------------------- /ch10-relational/templates/render_survey.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Render Survey Data 6 | 7 | 8 |

DataFrame representation:

9 | 10 | {{ data|safe }} 11 | 12 | -------------------------------------------------------------------------------- /ch10-relational/templates/upload_survey.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Upload Survey Data 6 | 7 | 8 |

Online Periodic Survey System

9 | 10 |
11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /ch11-app-decompose/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | WORKDIR /code 4 | 5 | COPY ./requirements.txt /code/requirements.txt 6 | RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt 7 | COPY ./ch11 /code 8 | EXPOSE 8000 9 | CMD ["uvicorn", "main:app", "--host=0.0.0.0" , "--reload" , "--port", "8000"] -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_django/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app-decompose/ch11/ch11_django/__init__.py -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_django/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for ch11_django project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_django/urls.py: -------------------------------------------------------------------------------- 1 | """ch11_django URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from sports import views 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('index/', views.view_index) 22 | ] 23 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_django/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for ch11_django project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_flask/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app-decompose/ch11/ch11_flask/api/__init__.py -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_flask/api/schedule.py: -------------------------------------------------------------------------------- 1 | from ch11_flask.app import app 2 | 3 | @app.route("/index") 4 | def testing(): 5 | return "flask integration" -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/ch11_flask/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | from ch11_flask.api import schedule 6 | 7 | if __name__ == '__main__': 8 | app.run() -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/config/db.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.osms 10 | 11 | users = db["login"] 12 | players = db["player"] 13 | officials = db["official"] 14 | return {"users": users, "players": players, "officials": officials} 15 | 16 | def close_async_db(): 17 | client.close() -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app-decompose/ch11/db.sqlite3 -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app-decompose/ch11/sports/__init__.py -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SportsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'sports' 7 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app-decompose/ch11/sports/migrations/__init__.py -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /ch11-app-decompose/ch11/sports/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http.request import HttpRequest 3 | from django.http.response import HttpResponse 4 | 5 | def view_index(req: HttpRequest): 6 | return HttpResponse(content="django integration") 7 | -------------------------------------------------------------------------------- /ch11-app-decompose/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | ch11-mongo: 4 | image: "mongo:latest" 5 | ports: 6 | - 27017:27017 7 | expose: 8 | - 27017 9 | networks: 10 | - ch11-network 11 | 12 | ch11-app: 13 | build: . 14 | depends_on: 15 | - ch11-mongo 16 | ports: 17 | - 8000:8000 18 | networks: 19 | - ch11-network 20 | networks: 21 | ch11-network: 22 | driver: bridge -------------------------------------------------------------------------------- /ch11-app-decompose/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Online Sports Management System for Docker Compose 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: June 19, 2022 6 | 7 | =========================== Description ================================== 8 | It has the same application but contains Docker Compose files. 9 | 10 | -------------------------------------------------------------------------------- /ch11-app-decompose/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | asgiref==3.5.2 3 | click==8.1.3 4 | colorama==0.4.4 5 | fastapi==0.78.0 6 | h11==0.13.0 7 | idna==3.3 8 | motor==3.0.0 9 | pydantic==1.9.1 10 | pymongo==4.1.1 11 | sniffio==1.2.0 12 | starlette==0.19.1 13 | typing_extensions==4.2.0 14 | uvicorn==0.17.6 15 | -------------------------------------------------------------------------------- /ch11-app-proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | COPY ./nginx_config.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /ch11-app-proxy/nginx_config.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8080; 3 | 4 | location / { 5 | proxy_pass http://192.168.1.7:8000; 6 | } 7 | 8 | } -------------------------------------------------------------------------------- /ch11-app-proxy/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Online Sports Management System for API Gateway 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: June 19, 2022 6 | 7 | =========================== Description ================================== 8 | This contains files for NGINX image deployment. 9 | -------------------------------------------------------------------------------- /ch11-app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | WORKDIR /code 4 | 5 | COPY ./requirements.txt /code/requirements.txt 6 | RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt 7 | COPY ./ch11 /code 8 | EXPOSE 8000 9 | CMD ["uvicorn", "main:app", "--host=0.0.0.0" , "--reload" , "--port", "8000"] -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_django/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app/ch11/ch11_django/__init__.py -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_django/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for ch11_django project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_django/urls.py: -------------------------------------------------------------------------------- 1 | """ch11_django URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from sports import views 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('index/', views.view_index) 22 | ] 23 | -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_django/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for ch11_django project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_flask/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app/ch11/ch11_flask/api/__init__.py -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_flask/api/schedule.py: -------------------------------------------------------------------------------- 1 | from ch11_flask.app import app 2 | 3 | @app.route("/index") 4 | def testing(): 5 | return "flask integration" -------------------------------------------------------------------------------- /ch11-app/ch11/ch11_flask/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | from ch11_flask.api import schedule 6 | 7 | if __name__ == '__main__': 8 | app.run() -------------------------------------------------------------------------------- /ch11-app/ch11/config/db.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.osms 10 | 11 | users = db["login"] 12 | players = db["player"] 13 | officials = db["official"] 14 | return {"users": users, "players": players, "officials": officials} 15 | 16 | def close_async_db(): 17 | client.close() -------------------------------------------------------------------------------- /ch11-app/ch11/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app/ch11/db.sqlite3 -------------------------------------------------------------------------------- /ch11-app/ch11/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /ch11-app/ch11/sports/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app/ch11/sports/__init__.py -------------------------------------------------------------------------------- /ch11-app/ch11/sports/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /ch11-app/ch11/sports/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SportsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'sports' 7 | -------------------------------------------------------------------------------- /ch11-app/ch11/sports/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-app/ch11/sports/migrations/__init__.py -------------------------------------------------------------------------------- /ch11-app/ch11/sports/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /ch11-app/ch11/sports/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /ch11-app/ch11/sports/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http.request import HttpRequest 3 | from django.http.response import HttpResponse 4 | 5 | def view_index(req: HttpRequest): 6 | return HttpResponse(content="django integration") 7 | -------------------------------------------------------------------------------- /ch11-app/readme.txt: -------------------------------------------------------------------------------- 1 | =========================== Basic Details ================================== 2 | Application Name: Online Sports Management System for Dockerization 3 | Developer: Sherwin John Calleja Tragura 4 | Status: Prototype stage 5 | Date finished: June 19, 2022 6 | 7 | =========================== Description ================================== 8 | It has the same application but contains Docker files. 9 | 10 | -------------------------------------------------------------------------------- /ch11-app/requirements.txt: -------------------------------------------------------------------------------- 1 | anyio==3.6.1 2 | asgiref==3.5.2 3 | click==8.1.3 4 | colorama==0.4.4 5 | fastapi==0.78.0 6 | h11==0.13.0 7 | idna==3.3 8 | motor==3.0.0 9 | pydantic==1.9.1 10 | pymongo==4.1.1 11 | sniffio==1.2.0 12 | starlette==0.19.1 13 | typing_extensions==4.2.0 14 | uvicorn==0.17.6 15 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/HELP.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ### Reference Documentation 4 | For further reference, please consider the following sections: 5 | 6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.7.0/maven-plugin/reference/html/) 8 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.7.0/maven-plugin/reference/html/#build-image) 9 | * [Eureka Server](https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/#spring-cloud-eureka-server) 10 | 11 | ### Guides 12 | The following guides illustrate how to use some features concretely: 13 | 14 | * [Service Registration and Discovery with Eureka and Spring Cloud](https://spring.io/guides/gs/service-registration-and-discovery/) 15 | 16 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/src/main/java/org/packt/chapter11/registry/ServerRegistryApplication.java: -------------------------------------------------------------------------------- 1 | package org.packt.chapter11.registry; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class ServerRegistryApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ServerRegistryApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | server.port=8761 3 | server.shutdown=graceful 4 | 5 | spring.cloud.inetutils.timeout-seconds: 10 6 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/src/test/java/com/example/demo/ServerRegistryApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ServerRegistryApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/target/classes/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Build-Jdk-Spec: 17 3 | Implementation-Title: demo 4 | Implementation-Version: 0.0.1-SNAPSHOT 5 | Created-By: Maven Integration for Eclipse 6 | 7 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/target/classes/META-INF/maven/com.example/demo/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Sun Jul 17 23:59:16 PST 2022 3 | m2e.projectLocation=C\:\\Alibata\\Training\\Source\\fastapi\\ch11-ws-eureka\\ch11-eureka-server 4 | m2e.projectName=ch11-eureka-server 5 | groupId=com.example 6 | artifactId=demo 7 | version=0.0.1-SNAPSHOT 8 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/target/classes/application.properties: -------------------------------------------------------------------------------- 1 | 2 | server.port=8761 3 | server.shutdown=graceful 4 | 5 | spring.cloud.inetutils.timeout-seconds: 10 6 | -------------------------------------------------------------------------------- /ch11-ws-eureka/ch11-eureka-server/target/classes/org/packt/chapter11/registry/ServerRegistryApplication.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11-ws-eureka/ch11-eureka-server/target/classes/org/packt/chapter11/registry/ServerRegistryApplication.class -------------------------------------------------------------------------------- /ch11/ch11_django/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11/ch11_django/__init__.py -------------------------------------------------------------------------------- /ch11/ch11_django/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for ch11_django project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /ch11/ch11_django/urls.py: -------------------------------------------------------------------------------- 1 | """ch11_django URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from sports import views 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | path('index/', views.view_index) 22 | ] 23 | -------------------------------------------------------------------------------- /ch11/ch11_django/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for ch11_django project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /ch11/ch11_flask/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11/ch11_flask/api/__init__.py -------------------------------------------------------------------------------- /ch11/ch11_flask/api/schedule.py: -------------------------------------------------------------------------------- 1 | from ch11_flask.app import app 2 | 3 | @app.route("/index") 4 | def testing(): 5 | return "flask integration" -------------------------------------------------------------------------------- /ch11/ch11_flask/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | 5 | from ch11_flask.api import schedule 6 | 7 | if __name__ == '__main__': 8 | app.run() -------------------------------------------------------------------------------- /ch11/config/db.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.osms 10 | 11 | users = db["login"] 12 | players = db["player"] 13 | officials = db["official"] 14 | return {"users": users, "players": players, "officials": officials} 15 | 16 | def close_async_db(): 17 | client.close() -------------------------------------------------------------------------------- /ch11/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11/db.sqlite3 -------------------------------------------------------------------------------- /ch11/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ch11_django.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /ch11/sports/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11/sports/__init__.py -------------------------------------------------------------------------------- /ch11/sports/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /ch11/sports/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SportsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'sports' 7 | -------------------------------------------------------------------------------- /ch11/sports/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/ch11/sports/migrations/__init__.py -------------------------------------------------------------------------------- /ch11/sports/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /ch11/sports/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /ch11/sports/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http.request import HttpRequest 3 | from django.http.response import HttpResponse 4 | 5 | def view_index(req: HttpRequest): 6 | return HttpResponse(content="django integration") 7 | -------------------------------------------------------------------------------- /database/osms_db.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/fed813478250b72db80b4c954c4693c0479d2a01/database/osms_db.zip --------------------------------------------------------------------------------