From ddee74d99154a6dcf0f8a9ea5d2d260c213c9855 Mon Sep 17 00:00:00 2001 From: fejao <mail@fejao.de> Date: Tue, 21 Jan 2025 18:36:02 +0000 Subject: [PATCH] Post 38c3 02 --- Makefile | 46 +- README.md | 349 +++++--- ci-cd/requirements.txt | 4 + data/db.json | 2 +- data/usage.ini | 10 +- docker/app/Dockerfile | 9 +- docker/cups/printers.conf | 24 + docker/docker-compose.yml | 67 +- src/config.yml | 44 +- src/main.py | 43 +- src/requirements.txt | 8 +- src/settings.py | 16 +- src/tests/files/2025_01_17_Graphana.png | Bin 0 -> 88771 bytes src/tests/files/2025_01_17_Graphana_2.png | Bin 0 -> 77268 bytes src/tests/utils/test_app_db.py | 124 --- src/tests/utils/test_app_printer.py | 2 + src/tests/web/test_server.py | 44 +- src/utils/__init__.py | 3 +- src/utils/app_configuration.py | 341 +++++++- src/utils/app_default_vals.py | 42 +- src/utils/app_files.py | 19 +- src/utils/app_influxdb.py | 446 +++++++++++ src/utils/{app_db.py => app_local_db.py} | 6 +- src/utils/app_printer.py | 35 +- src/utils/app_usage.py | 341 +++++++- src/web/__init__.py | 1 + src/web/routes_api.py | 752 ++++++++++++++++++ src/web/routes_debug.py | 64 +- src/web/routes_default_vals.py | 32 +- src/web/routes_protected.py | 280 +++++-- src/web/routes_user.py | 7 +- src/web/server.py | 111 ++- src/web/templates/debug_api.html | 71 ++ .../{debug_admin.html => debug_sys.html} | 3 +- src/web/templates/home_admin.html | 35 +- src/web/templates/layout_admin.html | 56 +- src/web/templates/upload_clean.html | 126 ++- src/web/templates/upload_list.html | 52 +- ...025-01-15_-_20-01-36___-___test_file_1.pdf | Bin 9819 -> 0 bytes 39 files changed, 3099 insertions(+), 516 deletions(-) create mode 100644 docker/cups/printers.conf create mode 100644 src/tests/files/2025_01_17_Graphana.png create mode 100644 src/tests/files/2025_01_17_Graphana_2.png delete mode 100644 src/tests/utils/test_app_db.py create mode 100644 src/utils/app_influxdb.py rename src/utils/{app_db.py => app_local_db.py} (96%) create mode 100644 src/web/routes_api.py create mode 100644 src/web/templates/debug_api.html rename src/web/templates/{debug_admin.html => debug_sys.html} (98%) delete mode 100644 uploads/429-359-943___-___2025-01-15_-_20-01-36___-___test_file_1.pdf diff --git a/Makefile b/Makefile index 1285bfa..0702542 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,14 @@ FOO="bar" PYTHON_VENV_PATH="/opt/c3printing/" CONTAINER_IMAGE_NAME_APP=c3printing-app +CONTAINER_IMAGE_NAME_INFLUXDB=c3printing-influxdb CONTAINER_IMAGE_NAME_CUPS=c3printing-cups CONTAINER_IMAGE_NAME_PROXY=c3printing-proxy CONTAINER_IMAGE_VERSION=latest -CONTAINER_NAME_APP=c3printing-app CONTAINER_NAME_CUPS=c3printing-cups +CONTAINER_NAME_INFLUXDB=c3printing-influxdb +# CONTAINER_NAME_INFLUXDB=influxdb +CONTAINER_NAME_APP=c3printing-app CONTAINER_NAME_PROXY=c3printing-proxy DOCKER_COMPOSE_CONF_PATH=foo @@ -23,13 +26,16 @@ help: docker_build_cups: ## Build local docker image from Dockerfile from cups. docker build . -t ${CONTAINER_IMAGE_NAME_CUPS}:${CONTAINER_IMAGE_VERSION} -f docker/cups/Dockerfile +docker_build_influxdb: ## Build local docker image from Dockerfile from influxdb. + docker build . -t ${CONTAINER_IMAGE_NAME_CUPS}:${CONTAINER_IMAGE_VERSION} -f docker/cups/Dockerfile + docker_build_app: ## Build local docker image from Dockerfile from app. docker build . -t ${CONTAINER_IMAGE_NAME_APP}:${CONTAINER_IMAGE_VERSION} -f docker/app/Dockerfile docker_build_proxy: ## Build local docker image from Dockerfile from proxy. docker build . -t ${CONTAINER_IMAGE_NAME_PROXY}:${CONTAINER_IMAGE_VERSION} -f docker/proxy/Dockerfile -docker_build_all: docker_build_app docker_build_cups docker_build_proxy ## Build local docker image from Dockerfile from all. +docker_build_all: docker_build_cups docker_build_influxdb docker_build_app docker_build_proxy ## Build local docker image from Dockerfile from all. ### ### DOCKER CREATE @@ -37,13 +43,16 @@ docker_build_all: docker_build_app docker_build_cups docker_build_proxy ## Build docker_create_cups: ## Create the local cups container. docker compose -f docker/docker-compose.yml create cups +docker_create_influxdb: ## Create the local inluxdb container. + docker compose -f docker/docker-compose.yml create influxdb + docker_create_app: ## Create the local app container. docker compose -f docker/docker-compose.yml create app docker_create_proxy: ## Create the local app container. docker compose -f docker/docker-compose.yml create proxy -docker_create_all: docker_create_cups docker_create_app docker_create_proxy ## Create all containers. +docker_create_all: docker_create_cups docker_create_influxdb docker_create_app docker_create_proxy ## Create all containers. ### ### DOCKER START @@ -51,16 +60,19 @@ docker_create_all: docker_create_cups docker_create_app docker_create_proxy ## C docker_start_cups: ## Start the local cups container. docker compose -f docker/docker-compose.yml start cups +docker_start_influxdb: ## Start the local influxdb container. + docker compose -f docker/docker-compose.yml start influxdb + docker_start_app: ## Start the local cups container. docker compose -f docker/docker-compose.yml start app docker_start_proxy: ## Start the local proxy container. docker compose -f docker/docker-compose.yml start proxy -docker_start_all: docker_start_cups docker_start_app docker_start_proxy ## Start all containers. +docker_start_all: docker_start_cups docker_start_influxdb docker_start_app docker_start_proxy ## Start all containers. ### -### RUN +### DOCKER RUN ### docker_run: ## Runs the app at the containers. docker compose -f docker/docker-compose.yml up -d @@ -72,13 +84,16 @@ docker_run: ## Runs the app at the containers. docker_stop_app: ## Stop the local app container. docker compose -f docker/docker-compose.yml stop app +docker_stop_influxdb: ## Stop the local influxdb container. + docker compose -f docker/docker-compose.yml stop influxdb + docker_stop_cups: ## Stop the local cups container. docker compose -f docker/docker-compose.yml stop cups docker_stop_proxy: ## Stop the local proxy container. docker compose -f docker/docker-compose.yml stop proxy -docker_stop_all: docker_stop_proxy docker_stop_app docker_stop_cups ## Stop the all containers. +docker_stop_all: docker_stop_proxy docker_stop_app docker_stop_influxdb docker_stop_cups ## Stop the all containers. ### ### DOCKER REMOVE @@ -108,7 +123,7 @@ local_test_lint: ## Runs locally lint tests locally. find ./src -type f -name "*.py" | xargs pylint local_test_unit_single: ## Runs locally unit-tests locally for app_printer. - python3 /home/fejao/.local/lib/python3.10/site-packages/pytest/__main__.py tests/utils/test_app_printer.py + python3 /home/fejao/.local/lib/python3.10/site-packages/pytest/__main__.py tests/web/test_server.py local_test_unit_all: ## Runs locally unit-tests locally for all files. python3 -m pytest @@ -119,12 +134,15 @@ local_run: ## Runs locally the app locally. python3 main.py ### DEBUG -debug_container_connect_app: ## Connects to the app container. - docker exec -it ${CONTAINER_NAME_APP} /bin/bash - debug_container_connect_cups: ## Connects to the cups container. docker exec -it ${CONTAINER_NAME_CUPS} /bin/bash +debug_container_connect_influxdb: ## Connects to the app container. + docker exec -it ${CONTAINER_NAME_INFLUXDB} /bin/bash + +debug_container_connect_app: ## Connects to the app container. + docker exec -it ${CONTAINER_NAME_APP} /bin/bash + debug_container_connect_proxy: ## Connects to the proxy container. docker exec -it ${CONTAINER_NAME_PROXY} /bin/bash @@ -136,3 +154,11 @@ debug_proxy_start: docker_create_proxy docker_start_proxy ## Debug start the pro debug_proxy_remove: ## Debug remove the proxy container. docker stop ${CONTAINER_NAME_PROXY} &&\ docker rm ${CONTAINER_NAME_PROXY} + +debug_influxdb_remove: ## Debug remove the proxy container. + docker stop ${CONTAINER_NAME_INFLUXDB} &&\ + docker rm ${CONTAINER_NAME_INFLUXDB} + +debug_influxdb_set: ## Debug remove the proxy container. + docker compose -f docker/docker-compose.yml create influxdb &&\ + docker compose -f docker/docker-compose.yml start influxdb diff --git a/README.md b/README.md index 58073c8..fd6f803 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -# c3infodesk - ---- +# c3InfoDesk Printer ## WIP - [x] Set the app for running over containers. @@ -9,6 +7,11 @@ --- +## What is this? +This is a repo for deploying the the printer system used at the c3infodesk for printing EXTREMILY NECESSARY documents + +--- + ## TL;DR ### 1- Clone the repo @@ -31,20 +34,76 @@ make docker_run --- -## Printers list -https://wiki.cccv.de/general/drucker +## Using the system with Docker containers + +### CUPS Problem +There's till the moment, no solution for setting the CUPS container without using the UI. +If you know any other way for doing it, please make a merge request. + +#### Stopping the host CUPS +First of all, at the host system, you should disable cups with: +```bash +systemctl stop cups +``` + +#### Find the Printer on the host +For using it with docker, you have first scan at the host system which port is the printer set +```bash +lsusb +``` + +You should update this at the **docker-compose.yml** file at: +```yaml + cups: + devices: + - /dev/bus/usb/001/007:/dev/bus/usb/001/007 +``` + +So the container can connect to the printer. + +#### Setting the Printer with it's Driver +Now you can go to the running CUPS from the container at the address: + +``` +http://localhosl:631 +``` + +And at the administration set the printer with it's driver or PPD file. + +**NOTE** +HP Printers are tricky to find the right driver. + +#### After printer with driver installed +Now will can start/re-start the others containers from the system + + +### Using InfluxDB +For using the API functionalities, you have to set the **ENABLED_INFLUXDB** to **true** + +Please check also the values at the **docker-compose.yml** and adjust it to your needs. + +#### WIP +At the moment, if the influxDB is enabled, I'm unable to set the App before generating a new token from the InfluxDB-UI :( + +The token used for generating the container can't be used for setting the organization, buckets and etc. +This step have to also be genareted manually, as the same as setting the printer from the CUPS container. +If you have an idea how to solve that, please make a merge request. + +So you have to start the system from the docker-compose and go trought the InfluxDB-UI for generating a new Token, then, update the value from **INFLUXDB_TOKEN** at the **docker-compose.yml** file with the new generated token. +After that, it should work fine. +Restart the containers from **docker-compose.yml** and the app container should be running. --- -## What is this? -This is a repo for deploying the the printer system used at the c3infodesk for printing EXTREMILY NECESSARY documents +## Printers list +https://wiki.cccv.de/general/drucker + --- ## Installing the the system Just clone this repo to your computer/Pi. Use the functions/commands setted over the **Makefile** - --- ## Using the Makefile @@ -91,68 +150,19 @@ local_test_unit Runs locally unit-tests locally. --- ## Adjusting the system -You can set all variables at the **config.yml** file or setting System environmemts variables or parsing the parameters - -### Parsing the values - -```bash -python3 main.py --help - -usage: main.py [-h] [-d] [-v] [-lf] [-umd] [-eq] [-ea] [-pu PATH_TO_UPLOAD] [-pl PATH_TO_LOG] [-pd PATH_TO_DB] - [-pt PATH_TEST_FILE] [-p PORT_SERVER] [-lfm LOG_FILE_MODE] [-f LOG_FORMAT] [-pn PRINTER_NAME] [-lp LOGIN_PASSWD] - [-le LOGIN_EMAIL] [-ka KEEP_ALIVE] [-nd NUM_DIGITS] [-muf MAX_UPLOAD_BYTES_FOLDER] [-mu MAX_UPLOAD_BYTES_FILE] - [-df DATE_FORMAT] [-afe ALLOWED_FILE_EXTENSIONS] [-fpw FILE_PREVIEW_WIDTH] [-fph FILE_PREVIEW_HEIGHT] +You can adjust the system in 3 ways +- Editing the **config.yml** +- Setting **environmental variables** +- Parsing values to the python command -c3 InfoDesk Printer - -options: - -h, --help show this help message and exit - -d, --debug Enable debugging information from execution. - -v, --verbose Enable printing information from execution. - -lf, --log_to_file Enable writing the log to a file. - -umd, --use_mem_db If using the TinyDB in memory or file. - -eq, --enabled_questions - If using the questions functionality. - -ea, --enabled_about If using the about functionality. - -pu PATH_TO_UPLOAD, --path_to_upload PATH_TO_UPLOAD - Path where the printing files should be uploaded. - -pl PATH_TO_LOG, --path_to_log PATH_TO_LOG - Path where the log file should be written. - -pd PATH_TO_DB, --path_to_db PATH_TO_DB - Path where the db file should be written. - -pt PATH_TEST_FILE, --path_test_file PATH_TEST_FILE - Path where the test print file location. - -p PORT_SERVER, --port_server PORT_SERVER - The port of the system - -lfm LOG_FILE_MODE, --log_file_mode LOG_FILE_MODE - Mode that the log file should be written, it can be: 'append' or 'new'. - -f LOG_FORMAT, --log_format LOG_FORMAT - Log format to be used. - -pn PRINTER_NAME, --printer_name PRINTER_NAME - Name of the printer to be used. - -lp LOGIN_PASSWD, --login_passwd LOGIN_PASSWD - Password to be used for login and printing. - -le LOGIN_EMAIL, --login_email LOGIN_EMAIL - Email to be used for login and printing. - -ka KEEP_ALIVE, --keep_alive KEEP_ALIVE - The amount of minutes to keep the file at the server before deletion. - -nd NUM_DIGITS, --num_digits NUM_DIGITS - The lenght of the generated code from the file to be printed. - -muf MAX_UPLOAD_BYTES_FOLDER, --max_upload_bytes_folder MAX_UPLOAD_BYTES_FOLDER - The maximum size in bytes that can be upload folder can keep. - -mu MAX_UPLOAD_BYTES_FILE, --max_upload_bytes_file MAX_UPLOAD_BYTES_FILE - The maximum size in bytes from a file that can be uploaded. - -df DATE_FORMAT, --date_format DATE_FORMAT - The date format to be used handiling the system. - -afe ALLOWED_FILE_EXTENSIONS, --allowed_file_extensions ALLOWED_FILE_EXTENSIONS - The allowed file extensions that the system can use. - -fpw FILE_PREVIEW_WIDTH, --file_preview_width FILE_PREVIEW_WIDTH - The width at the webpage for previewing a file. - -fph FILE_PREVIEW_HEIGHT, --file_preview_height FILE_PREVIEW_HEIGHT - The height at the webpage for previewing a file. +The hierarchy from each value will be over-writen is: +``` +config.yml --> environmental variables --> parsed values ``` +This means that the parsed values will have priority from the other 2 ones. + ### System Environments This are the system environments that can be set for running the script. @@ -160,6 +170,7 @@ This are the system environments that can be set for running the script. - **SERVER_PORT**=8000 - **SERVER_SECRET_KEY**=123456 - **DEBUG**=true +- **DEBUG_DISABLE_PRINTING**=false - **VERBOSE**=true - **LOG_TO_FILE**=false - **PATH_UPLOAD**=/c3printing/uploads @@ -170,6 +181,8 @@ This are the system environments that can be set for running the script. - **LOGIN_USER_PASSWD**=123456 - **LOGIN_ADMIN_EMAIL**=foo@bar.net - **LOGIN_ADMIN_PASSWD**=123456 +- **LOGIN_API_EMAIL**=foo@bar.net +- **LOGIN_API_PASSWD**=123456 - **LOG_MODE**=append - **LOG_FORMAT**=%(asctime)s - %(levelname)s - %(module)s - %(funcName)s - %(message)s - **KEEP_ALIVE_MIN**=15 @@ -179,41 +192,137 @@ This are the system environments that can be set for running the script. - **DATE_FORMAT**=%Y-%m-%d_-_%H-%M-%S - **ALLOWED_FILE_EXTENSIONS**="{'png', 'jpg', 'jpeg', 'gif', 'pdf'}" - **USE_MEM_DB**=false +- **ENABLED_PRINT_WITH_OPTIONS**=true - **ENABLED_QUESTIONS**=false - **ENABLED_ABOUT**=false -- **ENABLED_PRINT_WITH_OPTIONS**=true +- **ENABLED_API**=false +- **ENABLED_INFLUXDB**=false - **FILE_PREVIEW_WIDTH**=800 - **FILE_PREVIEW_HEIGHT**=600 - **FILE_AUTO_DELETE_AFTER_PRINT**=false +- **API_TOKEN_EXPIRE_HOURS**=120 +- **INFLUXDB_TOKEN**='Please set the influxdb token' +- **INFLUXDB_PORT**=8086 +- **INFLUXDB_URL**='http://localhost' +- **INFLUXDB_MEASUREMENT**='app-usage' +- **INFLUXDB_ROTATION_MINUTES**=2 +- **INFLUXDB_BUCKET**='c3infodesk-print' +- **INFLUXDB_BUCKET_DESCRIPTION**='Bucket used from InfoDesk at the 39c3' +- **INFLUXDB_BUCKET_RETENTION_DAYS**=10 ---- - -## Docker container -**WIP** - Working on reconizing the printer on the container using cups -> missing drivers -> ??? update to newer docker img ??? +### Parsing the values +You can see the options by running the command: -First of all, at the host system, you should disable cups with: ```bash -systemctl stop cups +python3 src/main.py --help ``` -For using it with docker, you have first scan at the host system which port is the printer set +The options are: ```bash -lsusb -``` - -You should update this at the docker-compose.yml file at: -```yaml - devices: - - /dev/bus/usb/001/007:/dev/bus/usb/001/007 -``` - -So the container can connect to the printer. - -After, you have to set the printer at the container CUPS +usage: main.py [-h] [--debug] [--debug_disable_printing] [--verbose] [--log_to_file] [--use_mem_db] [--enabled_questions] [--enabled_about] + [--enabled_print_with_options] [--enabled_api] [--enabled_influxdb] [--file_auto_delete_after_print] [--path_to_upload PATH_TO_UPLOAD] + [--path_to_log PATH_TO_LOG] [--path_to_data PATH_TO_DATA] [--path_test_file PATH_TEST_FILE] [--port_server PORT_SERVER] + [--server_secret_key SERVER_SECRET_KEY] [--log_file_mode LOG_FILE_MODE] [--log_format LOG_FORMAT] [--printer_name PRINTER_NAME] + [--login_user_email LOGIN_USER_EMAIL] [--login_user_passwd LOGIN_USER_PASSWD] [--login_admin_email LOGIN_ADMIN_EMAIL] + [--login_admin_passwd LOGIN_ADMIN_PASSWD] [--login_api_email LOGIN_API_EMAIL] [--login_api_passwd LOGIN_API_PASSWD] [--keep_alive KEEP_ALIVE] + [--num_digits NUM_DIGITS] [--max_upload_bytes_folder MAX_UPLOAD_BYTES_FOLDER] [--max_upload_bytes_file MAX_UPLOAD_BYTES_FILE] + [--max_upload_pdf_pages MAX_UPLOAD_PDF_PAGES] [--max_upload_file_copies MAX_UPLOAD_FILE_COPIES] [--date_format DATE_FORMAT] + [--allowed_file_extensions ALLOWED_FILE_EXTENSIONS] [--file_preview_width FILE_PREVIEW_WIDTH] [--file_preview_height FILE_PREVIEW_HEIGHT] + [--api_token_expire_hours API_TOKEN_EXPIRE_HOURS] [--influxdb_token INFLUXDB_TOKEN] [--influxdb_organization INFLUXDB_ORGANIZATION] + [--influxdb_port INFLUXDB_PORT] [--influxdb_url INFLUXDB_URL] [--influxdb_measurement INFLUXDB_MEASUREMENT] + [--influxdb_rotation_minutes INFLUXDB_ROTATION_MINUTES] [--influxdb_bucket INFLUXDB_BUCKET] + [--influxdb_bucket_description INFLUXDB_BUCKET_DESCRIPTION] [--influxdb_bucket_retention_days INFLUXDB_BUCKET_RETENTION_DAYS] -http://localhosl:631 +c3 InfoDesk Printer +options: + -h, --help show this help message and exit + --debug Enable debugging information from execution. + --debug_disable_printing + Disable the printing funcionallity for debugging. + --verbose Enable printing information from execution. + --log_to_file Enable writing the log to a file. + --use_mem_db If using the TinyDB in memory or file. + --enabled_questions If using the questions functionality. + --enabled_about If using the about functionality. + --enabled_print_with_options + If using the functionality for printing with options. + --enabled_api If using the API functionality. + --enabled_influxdb If using the InfluxDB functionality. + --file_auto_delete_after_print + If auto deleting the file after printing. + --path_to_upload PATH_TO_UPLOAD + Path where the printing files should be uploaded. + --path_to_log PATH_TO_LOG + Path where the log file should be written. + --path_to_data PATH_TO_DATA + Path where the app data should be written. + --path_test_file PATH_TEST_FILE + Path where the test print file location. + --port_server PORT_SERVER + The port of the system + --server_secret_key SERVER_SECRET_KEY + The secret key from the server + --log_file_mode LOG_FILE_MODE + Mode that the log file should be written, it can be: 'append' or 'new'. + --log_format LOG_FORMAT + Log format to be used. + --printer_name PRINTER_NAME + Name of the printer to be used. + --login_user_email LOGIN_USER_EMAIL + Email to be used for login as user for printing. + --login_user_passwd LOGIN_USER_PASSWD + Password to be used for login as user for printing. + --login_admin_email LOGIN_ADMIN_EMAIL + Email to be used for login as admin. + --login_admin_passwd LOGIN_ADMIN_PASSWD + Password to be used for login as admin. + --login_api_email LOGIN_API_EMAIL + Email to be used for login as api. + --login_api_passwd LOGIN_API_PASSWD + Password to be used for login as api. + --keep_alive KEEP_ALIVE + The amount of minutes to keep the file at the server before deletion. + --num_digits NUM_DIGITS + The lenght of the generated code from the file to be printed. + --max_upload_bytes_folder MAX_UPLOAD_BYTES_FOLDER + The maximum size in bytes that can be upload folder can keep. + --max_upload_bytes_file MAX_UPLOAD_BYTES_FILE + The maximum size in bytes from a file that can be uploaded. + --max_upload_pdf_pages MAX_UPLOAD_PDF_PAGES + The maximum number of pages from a PDF file that can be uploaded. + --max_upload_file_copies MAX_UPLOAD_FILE_COPIES + The maximum number of copies from a file that can be printed. + --date_format DATE_FORMAT + The date format to be used handiling the system. + --allowed_file_extensions ALLOWED_FILE_EXTENSIONS + The allowed file extensions that the system can use. + --file_preview_width FILE_PREVIEW_WIDTH + The width at the webpage for previewing a file. + --file_preview_height FILE_PREVIEW_HEIGHT + The height at the webpage for previewing a file. + --api_token_expire_hours API_TOKEN_EXPIRE_HOURS + How many hours till the API token to expire. + --influxdb_token INFLUXDB_TOKEN + The token to be used for InfluxDB. + --influxdb_organization INFLUXDB_ORGANIZATION + The organization to be used for InfluxDB. + --influxdb_port INFLUXDB_PORT + The port of the InfluxDB server. + --influxdb_url INFLUXDB_URL + The URL of the InfluxDB server. + --influxdb_measurement INFLUXDB_MEASUREMENT + The measurement name of the InfluxDB server. + --influxdb_rotation_minutes INFLUXDB_ROTATION_MINUTES + how many minutes to refresh the values at the InfluxDB server. + --influxdb_bucket INFLUXDB_BUCKET + The bucket name of the InfluxDB server. + --influxdb_bucket_description INFLUXDB_BUCKET_DESCRIPTION + The description from the bucket of the InfluxDB server. + --influxdb_bucket_retention_days INFLUXDB_BUCKET_RETENTION_DAYS + The retention days from the bucket of the InfluxDB server. +``` --- @@ -243,6 +352,7 @@ http://localhost - To logout at the app as administrator. ### Admin +These end-points are only accessible **when logged into the system**. - **/logout**: GET - Logout as admin. @@ -252,37 +362,82 @@ http://localhost - Show all the uploaded files. Here you can print or delete the uploaded files. - **/uploaded-clean**: GET - Nuke all uploaded files -- **/file-print**: +- **/file-print**: POST - Return page with the message from printing a file. -- **/file-delete**: POST - - Return page with the message from deleting a file. +- **/file-print-options**: POST + - Return page with the message from printing a file with printing options. - **/file-preview**: POST - Opens a new Tab with the file content. -- **/remove-all-files**: POST - - A route for nuking all files on the system. +- **/file-delete**: POST + - Return page with the message from deleting a file. - **/remove-all-files**: POST - A route for nuking all files on the system. - **/docs/index.html**: GET - A route for reading the documentaion of this project. ### Debug +These endpoints are only enable when **DEBUG** is set to **true** -- **/debug-printers**: GET - - Here you can list all the printers recognized from the app using CUPS. -- **/debug-print-test**: GET | POST - - Here you can try to print a test page using the system. So I don't have to upload allways to test printing. +- **/debug-printers**: GET | POST + - Here you can list all the printers recognized from the app using CUPS and printing a test file. +- **/debug-sys**: GET + - Display a couple of tips for debugging the system and also all the setted values. +- **/debug-api**: GET + - Display the generated **token_access** and **token_refresh** values. ### Questions +These endpoints are only enable when **ENABLED_QUESTIONS** is set to **true** -- **/most-asked-questions**: GET | POST +- **/most-asked-questions**: GET | POST - Read, update and add a new most common questions. - **/set-question**: GET | POST - Add or update the questions on the system. --- +--- + +## Accessing the System via API +For using the API functionalities, you have to set the **ENABLED_API** to **true** + + +### POST /api/login +Creating new tokens are only accessible when the app are running at **debug mode** + +```bash +curl -X POST \ + http://localhost:8000/api/login \ + -u api@39c3.local:123456 +``` + +### GET /api/create-refresh-token +```bash +curl -X POST \ + http://localhost:8000/api/create-refresh-token \ + -H 'Authorization: Bearer YOUR_REFRESH_TOKEN' \ + -H 'Content-Type: application/json' \ + -d '{"refresh_token": "YOUR_REFRESH_TOKEN"}' +``` + +### GET /api/test +```bash +curl -X GET \ + http://your-app-url.local/api/test \ + -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ + -H 'Content-Type: application/json' +``` + +--- + ## InfoDesk Printer ### 37c3 https://support.hp.com/de-de/drivers/hp-laserjet-pro-m402dn/model/7458632 +### 38c3 +TODO: Find this in WIKI + +--- + +## License + diff --git a/ci-cd/requirements.txt b/ci-cd/requirements.txt index 21d3072..aac4d5e 100644 --- a/ci-cd/requirements.txt +++ b/ci-cd/requirements.txt @@ -10,6 +10,10 @@ tinydb APScheduler pytz pypdf +### API +flask_jwt_extended +### INFLUXDB +influxdb-client ### TESTS pylint pylint_junit diff --git a/data/db.json b/data/db.json index 9b2f795..e9b1817 100644 --- a/data/db.json +++ b/data/db.json @@ -1 +1 @@ -{"_default": {"1": {"file_code": "429-359-943", "uploaded_date": "2025-01-15_-_20-01-36", "original_name": "test_file_1.pdf", "new_file_name": "429-359-943___-___2025-01-15_-_20-01-36___-___test_file_1.pdf", "path": "/home/fejao/Coding/CCC/Repos/c3infodesk/c3printer/uploads/429-359-943___-___2025-01-15_-_20-01-36___-___test_file_1.pdf", "num_pages": 1}}} \ No newline at end of file +{"_default": {}} \ No newline at end of file diff --git a/data/usage.ini b/data/usage.ini index 7e8c7cd..b700753 100644 --- a/data/usage.ini +++ b/data/usage.ini @@ -2,11 +2,17 @@ total = 1 [PRINTS] -total = 1 +total = 0 [PAGES] -total = 1 +total = 0 [MAX_SIMULTANEOUS_UPLOADS] total = 1 +[FILES] +total = 0 + +[TOTAL_SIZE_UPLOAD] +total = 0 + diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile index d903d44..4c59b58 100644 --- a/docker/app/Dockerfile +++ b/docker/app/Dockerfile @@ -14,12 +14,17 @@ RUN apt-get update -qq && apt-get upgrade -qqy \ # Copy app to the container WORKDIR /c3printing +COPY ../../src /c3printing/src +RUN pip3 install -r src/requirements.txt + +# Copy the rest of the app to the container COPY ../../data /c3printing/data COPY ../../logs /c3printing/logs COPY ../../uploads /c3printing/uploads -COPY ../../src /c3printing/src -RUN pip3 install -r src/requirements.txt WORKDIR /c3printing/src +### DEBUG +# ENTRYPOINT ["/bin/sh", "-c" , "sleep 10000000"] + ENTRYPOINT ["/bin/sh", "-c" , "python3 main.py"] diff --git a/docker/cups/printers.conf b/docker/cups/printers.conf new file mode 100644 index 0000000..23ce6dc --- /dev/null +++ b/docker/cups/printers.conf @@ -0,0 +1,24 @@ +# Printer configuration file for CUPS v2.4.2 +# Written by cupsd +# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING +NextPrinterId 3 +<Printer HP_LaserJet_M402n> +PrinterId 2 +UUID urn:uuid:d1d9cd1c-e878-3e65-7157-883ead742ade +Info HP LaserJet M402n +Location infodesk +MakeModel HP LaserJet Pro M402-M403 Postscript (recommended) +DeviceURI usb://HP/LaserJet%20M402n?serial=PHCGC58854 +State Idle +StateTime 1735157141 +ConfigTime 1735157159 +Type 8425684 +Accepting Yes +Shared No +JobSheets none none +QuotaPeriod 0 +PageLimit 0 +KLimit 0 +OpPolicy default +ErrorPolicy retry-job +</Printer> diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index fa2cede..50e436f 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -13,15 +13,52 @@ services: interval: 5s timeout: 5s retries: 5 - # ports: - # - 631:631 + ### THIS SHOULD NOT SET FOR PRODUCTION + ports: + - 631:631 devices: ### You should scan which printer with lsub - - /dev/bus/usb/001/005:/dev/bus/usb/001/005 + # - /dev/bus/usb/001/005:/dev/bus/usb/001/005 + - /dev/bus/usb/001:/dev/bus/usb/001 volumes: - /var/run/dbus:/var/run/dbus - /dev/bus/usb:/dev/bus/usb - cups_socket:/run/cups + ### MOUNT LOCAL -> CONFIG AND PRINTERS + - ./cups/cupsd.conf:/etc/cups/cupsd.conf + - ./cups/printers.conf:/etc/cups/printers.conf + ### + ### INFLUXDB + ### + influxdb: + image: influxdb:2.7.11-alpine + container_name: c3printing-influxdb + # restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8086 || exit 1"] + interval: 5s + timeout: 5s + retries: 5 + ports: + - 8086:8086 + volumes: + - ./influxdb/data:/var/lib/influxdb2 + - ./influxdb/config:/etc/influxdb2 + environment: + - FOO=BAR + # - INFLUXDB_ADMIN_ENABLED=true + - INFLUXDB_TOKEN="myL9Rou80UKyqgHrRXNIOe1YtoU5L15PlIyPwFs-NZoJYLa2X2Mdu0sYgd1FYEEAeaLNW0VeaJYTivE5iBFyiQ==" + ### + ### INIT + ### + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=admin + - DOCKER_INFLUXDB_INIT_PASSWORD=12345678 + - DOCKER_INFLUXDB_INIT_ORG=c3infodesk + - DOCKER_INFLUXDB_INIT_BUCKET=c3infodesk-print + - DOCKER_INFLUXDB_INIT_RETENTION=1w + # - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN="my-super-secret-auth-token" + - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN="myL9Rou80UKyqgHrRXNIOe1YtoU5L15PlIyPwFs-NZoJYLa2X2Mdu0sYgd1FYEEAeaLNW0VeaJYTivE5iBFyiQ==" ### ### APP ### @@ -38,6 +75,8 @@ services: depends_on: cups: condition: service_healthy + influxdb: + condition: service_healthy links: - cups ports: @@ -48,6 +87,8 @@ services: - ../data:/c3printing/data - ../logs:/c3printing/logs - ../uploads:/c3printing/uploads + ### DEBUG + # - ../src/:/c3printing/src ### ### PLEASE SET THIS FIELDS, most are set from the Docker image ### @@ -60,6 +101,7 @@ services: - PATH_DATA=/c3printing/data - PATH_TEST_FILE=/c3printing/tests/files/test_file.pdf - DEBUG=true + - DEBUG_DISABLE_PRINTING=false - VERBOSE=true - SERVER_PORT=8000 - SERVER_SECRET_KEY=123456 @@ -67,6 +109,8 @@ services: - LOGIN_USER_PASSWD=123456 - LOGIN_ADMIN_EMAIL=admin@39c3.local - LOGIN_ADMIN_PASSWD=123456 + - LOGIN_API_EMAIL=api@39c3.local + - LOGIN_API_PASSWD=123456 - LOG_MODE=append - LOG_TO_FILE=false - KEEP_ALIVE_MIN=15 @@ -79,13 +123,28 @@ services: ### 16 Mb = 16 * 1024 * 1024 = 16777216 - MAX_UPLOAD_BYTES_FILE=16777216 ### If not using the printing with options functionality: true | false - - ENABLED_PRINT_WITH_OPTIONS=true + - ENABLED_PRINT_WITH_OPTIONS=false ### If not using the questions functionality: true | false - ENABLED_QUESTIONS=true + ### If not using the API functionality: true | false + - ENABLED_API=false + ### If not using the InfluxDB functionality: true | false + - ENABLED_INFLUXDB=false ### If using the DB on RAM only: true | false - USE_MEM_DB=false ### If it should delete the files after printing - FILE_AUTO_DELETE_AFTER_PRINT=false + - FILE_PREVIEW_WIDTH=800 + - FILE_PREVIEW_HEIGHT=600 + ### 5 days in hours = 120 + - API_TOKEN_EXPIRE_HOURS=120 + - INFLUXDB_TOKEN='Please set the influxdb token' + - INFLUXDB_PORT=8086 + - INFLUXDB_URL='http://localhost' + - INFLUXDB_BUCKET='c3infodesk-print' + - INFLUXDB_BUCKET_DESCRIPTION='Bucket used from InfoDesk at the 39c3' + - INFLUXDB_BUCKET_RETENTION_DAYS=10 + - INFLUXDB_MEASUREMENT='app-usage' ### ### PROXY ### diff --git a/src/config.yml b/src/config.yml index b8a2109..18c4ba8 100644 --- a/src/config.yml +++ b/src/config.yml @@ -15,12 +15,12 @@ default: ### ### SET OWN PROPERTIES: END ### - # login_email: 'foo@bar.net' - # login_passwd: '123456' login_user_email: 'angel@39c3.local' login_user_passwd: '123456' login_admin_email: 'admin@39c3.local' login_admin_passwd: '123456' + login_api_email: 'api@39c3.local' + login_api_passwd: '123456' ### ### ### @@ -36,14 +36,18 @@ default: # debug: false # verbose: false ### + debug_disable_printing: true + # debug_disable_printing: false + ### # log_to_file: true log_to_file: false ### - # log_file_mode: "append" - log_file_mode: "new" + log_file_mode: "append" + # log_file_mode: "new" ### # keep_file_minutes: 15 keep_file_minutes: 1 + # keep_file_minutes: 3 ### # You should use multiples of 3 -> (6 | 9) # num_digits: 6 @@ -66,11 +70,39 @@ default: # enabled_about: true enabled_about: false ### PRINT WITH OPTIONS - # enabled_print_with_options: true - enabled_print_with_options: false + enabled_print_with_options: true + # enabled_print_with_options: false + ### API + enabled_api: true + # enabled_api: false + ### INFLUXDB + enabled_influxdb: true + # enabled_influxdb: false ### FILE PREVIEW file_preview_width: '800' file_preview_height: '900' ### FILE AUTO DELETE AFTER PRINT # file_auto_delete_after_print: true file_auto_delete_after_print: false + ### API TOKEN EXPIRE + # 5 days in hours = 120 + api_token_expire_hours: 120 + ### + ### INFLUXDB + ### + + ### ORIG + # influxdb_token: "my-super-secret-auth-token" + # influxdb_token: "hMDdMGpjJH6AiAZaLpi3A0QXpJXLBiBYewcpmBWc2w-WHUW_fC1L_ZW4Y43Zx1uWZnlJ36SRZH7EqWqfAfa7GA==" + ### SET ON DOCKERFILE + # influxdb_token: "myL9Rou80UKyqgHrRXNIOe1YtoU5L15PlIyPwFs-NZoJYLa2X2Mdu0sYgd1FYEEAeaLNW0VeaJYTivE5iBFyiQ==" + ### + influxdb_token: "TwRkAaLUQIk97IJX9wgWgn4FRN_dm1Tvileh_63-sVdWyB6Xh25taaF_05RD8qiWPsb-BUAZKBv_p2Iq_Qe2Aw==" + influxdb_port: '8086' + influxdb_url: 'http://localhost' + influxdb_organization: 'c3infodesk' + influxdb_bucket: 'c3infodesk-print' + influxdb_measurement: 'app-usage' + influxdb_bucket_description: 'Bucket used from InfoDesk at the 39c3' + influxdb_bucket_retention_days: 10 + influxdb_rotation_minutes: 2 diff --git a/src/main.py b/src/main.py index 63e4cd3..dd1c6bb 100644 --- a/src/main.py +++ b/src/main.py @@ -49,12 +49,27 @@ def files_cleaner() -> None: """ logger("Starting files_cleaner...") - files_expired = settings._db.get_expired() + files_expired = settings._local_db.get_expired() for file in files_expired: ### DELETE FROM DISK settings._files.file_delete(file) ### DELETE FROM DB - settings._db.file_delete(file) + settings._local_db.file_delete(file) + ### DELETE FROM USAGE + settings._usage.update_from_delete() + + +def rotate_influxdb_values() -> None: + """ + Function to rotate the values at the InfluxDB. + + Returns + ------- + None + """ + + logger("Starting rotate_influxdb_values...") + settings._usage.influxdb_values_rotate() def start_web_server() -> None: @@ -93,21 +108,41 @@ def main() -> None: # print(settings._config) # print(settings._log) # print(settings._printer) - # print(settings._db) + # print(settings._local_db) + # print(settings._influx_db) # print(settings._files) # print(settings._web_server) #### #### DEBUG END #### - ## DELETE EXPIRED FILES IN BACKGROUND + #### + #### DEBUG INFLUXDB + #### + # settings._usage.influxdb_values_reset() + # import pdb; pdb.set_trace() + + ### SET SCHEDULER scheduler = BackgroundScheduler() + + ### DELETE EXPIRED FILES IN BACKGROUND scheduler.add_job( files_cleaner, 'interval', minutes=settings._config.keep_file_minutes ) logger("Starting background deleting expired files...") + + ### ROTATE VALUES ON THE INFLUXDB + if settings._config.enabled_influxdb: + scheduler.add_job( + rotate_influxdb_values, + 'interval', + minutes=settings._influx_db.rotation_minutes + ) + logger("Starting background rotating InfluxDB values...") + + ### START SCHEDULER scheduler.start() ### START THE APP diff --git a/src/requirements.txt b/src/requirements.txt index 7f4bde1..aed3caa 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -8,11 +8,13 @@ tinydb APScheduler pytz pypdf +### FLASK flask flask-login -# Flask -# Flask-SQLAlchemy -# Flask-Login +### API +flask_jwt_extended +### INFLUXDB +influxdb-client ### TESTS # pylint # pep8 diff --git a/src/settings.py b/src/settings.py index 6609e78..c155423 100644 --- a/src/settings.py +++ b/src/settings.py @@ -52,15 +52,25 @@ _log = set_logger(config=_config) _printer = utils.AppPrinter(config=_config) ### DB -_db = utils.AppDB(config=_config) +_local_db = utils.AppLocalDB(config=_config) ### FILES _files = utils.AppFiles(config=_config) +### INFLUXDB +if _config.enabled_influxdb: + _influx_db = utils.AppInfluxDB(config=_config) +else: + _influx_db = None + +### USAGE +_usage = utils.AppUsage(config=_config, influxdb=_influx_db) + ### FLASK _web_server = web.AppServer( config=_config, printer=_printer, - db_files=_db, - files=_files + db_files=_local_db, + files=_files, + usage=_usage ) diff --git a/src/tests/files/2025_01_17_Graphana.png b/src/tests/files/2025_01_17_Graphana.png new file mode 100644 index 0000000000000000000000000000000000000000..99477a02f431c169ceda7ce9bd494ad72f17080f GIT binary patch literal 88771 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 literal 0 HcmV?d00001 diff --git a/src/tests/files/2025_01_17_Graphana_2.png b/src/tests/files/2025_01_17_Graphana_2.png new file mode 100644 index 0000000000000000000000000000000000000000..4b0409ebfd2965514ec49bf5148aee510f28acab GIT binary patch literal 77268 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 QM?v#Up00i_>zopr0DdS$YXATM literal 0 HcmV?d00001 diff --git a/src/tests/utils/test_app_db.py b/src/tests/utils/test_app_db.py deleted file mode 100644 index 48c92a6..0000000 --- a/src/tests/utils/test_app_db.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 -""" - tests.test_app_db.py file for the c3 printing system. - File for testing the modules and functions from the utils.app_db.py file. -""" - -import unittest -from unittest.mock import patch, MagicMock - -### LOCAL -from utils.app_db import AppDB - -### -### VARIABLES -### -TEST_PATH_TO_DATA = '/tmp' - - -class TestAppDB(unittest.TestCase): - """ Class for testing the utils.AppDB methods. - """ - - @patch('utils.app_db.TinyDB') - def setUp(self, mock_tinydb): - """ Method for setup the test class. - """ - mock_config = MagicMock() - # Config setup - mock_config.path_to_data = TEST_PATH_TO_DATA - mock_config.use_mem_db = False - mock_config.keep_file_minutes = 30 - mock_config.date_format = "%Y-%m-%d" - - # Create AppDB instance - self.app_db = AppDB(mock_config) - - # Access the mocked TinyDB instance - self.mock_db = mock_tinydb.return_value - - @patch('utils.app_db.TinyDB') - @patch('utils.app_db.CachingMiddleware') - def test_set_db_mem(self, mock_caching_middleware, mock_tinydb): - """ Tests the AppDb as using the db at the memory and not at local file. - """ - self.app_db.config.use_mem_db = True - self.app_db.set_db() - - # Check if TinyDB was initialized with caching - mock_tinydb.assert_called_once_with( - TEST_PATH_TO_DATA + '/db.json', - storage=mock_caching_middleware.return_value - ) - - @patch('utils.app_db.TinyDB') # Ensure TinyDB is mocked at the class level - def test_set_db_file(self, mock_tinydb): - """ Tests the AppDb as using the db at local file. - """ - self.app_db.config.use_mem_db = False - self.app_db.set_db() - - # Check if TinyDB was called once with the correct path - mock_tinydb.assert_called_once_with(TEST_PATH_TO_DATA + '/db.json') - - def test_get_all(self): - """ Tests utils.app_db.get_all() method. - """ - expected_result = [{'file_code': 'test_code'}] - self.mock_db.all.return_value = expected_result - - result = self.app_db.get_all() - self.assertEqual(result, expected_result) - - def test_get_file_info(self): - """ Tests utils.app_db.get_file_info(file_core: str) method. - """ - expected_info = {'file_code': 'test_code'} - self.mock_db.search.return_value = [expected_info] - - result = self.app_db.get_file_info('test_code') - self.assertEqual(result, expected_info) - - def test_get_file_info_multiple_records(self): - """ Tests utils.app_db.get_file_info(file_core: str) method from multiple records. - """ - # Mocking a case where multiple records are found - duplicate_info = [{'file_code': 'test_code'}, {'file_code': 'test_code'}] - self.mock_db.search.return_value = duplicate_info - - result = self.app_db.get_file_info('test_code') - self.assertIn('error_message', result) # We expect an error message when multiple records are found - - def test_file_save(self): - """ Tests utils.app_db.file_save(file_info) method. - """ - file_info = {'file_code': 'test_code'} - self.mock_db.insert = MagicMock() - - # Attempt to save the file information - self.app_db.file_save(file_info) - self.mock_db.insert.assert_called_once_with(file_info) - - def test_file_delete(self): - """ Tests utils.app_db.file_delete(file_info) method. - """ - file_info = {'file_code': 'test_code'} - self.mock_db.remove = MagicMock() - - # Call the delete method - self.app_db.file_delete(file_info) - self.mock_db.remove.assert_called_once() - self.assertEqual(self.mock_db.remove.call_args[0][0], self.app_db.query.file_code == 'test_code') - - def test_remove_all_files(self): - """ Tests utils.app_db.remove_all_files() method. - """ - self.mock_db.drop_tables = MagicMock() - - # Call the method to remove all files - self.app_db.remove_all_files() - self.mock_db.drop_tables.assert_called_once() - - -if __name__ == '__main__': - unittest.main() diff --git a/src/tests/utils/test_app_printer.py b/src/tests/utils/test_app_printer.py index 9e9cc13..5bcf4c6 100644 --- a/src/tests/utils/test_app_printer.py +++ b/src/tests/utils/test_app_printer.py @@ -22,6 +22,7 @@ class TestAppPrinter(unittest.TestCase): # Mock the config object mock_config = MagicMock() mock_config.printer_name = 'Test Printer' + mock_config.debug_disable_printing = False # Create instance of AppPrinter app_printer = AppPrinter(mock_config) @@ -54,6 +55,7 @@ class TestAppPrinter(unittest.TestCase): """ mock_config = MagicMock() mock_config.printer_name = 'Test Printer' + mock_config.debug_disable_printing = False app_printer = AppPrinter(mock_config) file_path = 'test_document.txt' diff --git a/src/tests/web/test_server.py b/src/tests/web/test_server.py index f557616..d8d5f99 100644 --- a/src/tests/web/test_server.py +++ b/src/tests/web/test_server.py @@ -49,6 +49,11 @@ class TestAppServer(unittest.TestCase): self.mock_config.max_upload_bytes_folder = 10000000000 self.mock_config.num_digits = 6 self.mock_config.debug = True + ### + self.mock_config.verbose = True + self.mock_config.log_format = "%(asctime)s - %(levelname)s - %(module)s - %(funcName)s - %(message)s" + self.mock_config.log_to_file = False + self.mock_config.log_file_mode = "append" self.mock_config.num_digits = 6 self.mock_config.allowed_file_extensions = "{'txt', 'jpg', 'png', 'pdf'}" @@ -61,6 +66,7 @@ class TestAppServer(unittest.TestCase): self.mock_printer = MagicMock() self.mock_db_files = MagicMock() self.mock_files = AppFiles(config=self.mock_config) + self.mock_usage = MagicMock() # Create an instance of AppServer self.server = AppServer( @@ -68,6 +74,7 @@ class TestAppServer(unittest.TestCase): printer=self.mock_printer, db_files=self.mock_db_files, files=self.mock_files, + usage=self.mock_usage ) # Set up Flask test client @@ -283,13 +290,20 @@ class TestAppServer(unittest.TestCase): ### ### PROTECTED ### - @patch('utils.app_usage.AppUsage.counter_max_simultaneous_uploaded_get') - @patch('utils.app_usage.AppUsage.counter_pages_get') - @patch('utils.app_usage.AppUsage.counter_uploads_get') - @patch('utils.app_usage.AppUsage.counter_prints_get') - def test_home_admin_route_login(self, _, __, ___, ____): + @patch('web.routes_protected.AppRoutesProtected._get_counters_home_admin') + def test_home_admin_route_login(self, mock_get_counters): """ Test the home admin route. """ + ### Set mock + mock_get_counters.return_value = { + 'tot_uploads': 1, + 'tot_prints': 1, + 'tot_pages': 1, + 'tot_files_on_folder': 1, + 'tot_size': 1, + 'max_simultaneous_uploaded': 1, + } + # Test that the /home-admin route is accessible when logged in with self.client: # Simulate a login for the test @@ -297,6 +311,7 @@ class TestAppServer(unittest.TestCase): 'email': self.mock_config.login_user_email, 'password': self.mock_config.login_user_passwd }) + # import pdb; pdb.set_trace() response = self.client.get('/home-admin') # Expecting OK status self.assertEqual(response.status_code, 200) @@ -312,9 +327,16 @@ class TestAppServer(unittest.TestCase): # Expecting Unauthorized status self.assertEqual(response.status_code, 401) - def test_uploaded_list_route_login(self): + @patch('web.routes_protected.AppRoutesProtected._get_counters_uploaded_list') + def test_uploaded_list_route_login(self, mock_get_counters): """ Test the home admin route. """ + ### Set mock + mock_get_counters.return_value = { + 'tot_uploaded_files': 1, + 'tot_folder_size': 1, + } + # Test that the /home-admin route is accessible when logged in with self.client: # Simulate a login for the test @@ -496,7 +518,7 @@ class TestAppServer(unittest.TestCase): self.assertEqual(response.status_code, 401) def test_debug_admin_route_login_admin(self): - """ Test the /debug-admin route logged in. + """ Test the /debug-printers route logged in. """ with self.client: # Simulate a successful login @@ -505,11 +527,11 @@ class TestAppServer(unittest.TestCase): 'password': self.mock_config.login_admin_passwd }) - response = self.client.get('/debug-admin') + response = self.client.get('/debug-printers') # expect OK self.assertEqual(response.status_code, 200) # Assuming 'h1' in the home page content - page_h1 = DEFAULT_ROUTE_VALS.get('DEBUG_ADMIN').get('page_h1') + page_h1 = DEFAULT_ROUTE_VALS.get('DEBUG_PRINTERS').get('page_h1') self.assertIn(page_h1.encode('utf-8'), response.data) def test_debug_admin_route_login_user(self): @@ -522,7 +544,7 @@ class TestAppServer(unittest.TestCase): 'password': self.mock_config.login_user_passwd }) - response = self.client.get('/debug-admin') + response = self.client.get('/debug-printers') # expect not allowed self.assertEqual(response.status_code, 403) @@ -530,7 +552,7 @@ class TestAppServer(unittest.TestCase): """ Test the /debug-admin route logged out. """ # Test that the /debug-admin route is not accessible when not logged in - response = self.client.get('/debug-admin') + response = self.client.get('/debug-printers') # Expecting Unauthorized status self.assertEqual(response.status_code, 401) diff --git a/src/utils/__init__.py b/src/utils/__init__.py index 7d41083..4f5c5de 100644 --- a/src/utils/__init__.py +++ b/src/utils/__init__.py @@ -5,7 +5,8 @@ from utils.app_configuration import AppConfiguration -from utils.app_db import AppDB +from utils.app_influxdb import AppInfluxDB +from utils.app_local_db import AppLocalDB from utils.app_files import AppFiles from utils.app_printer import AppPrinter from utils.app_questions import AppQuestions diff --git a/src/utils/app_configuration.py b/src/utils/app_configuration.py index 94259dc..3024c64 100644 --- a/src/utils/app_configuration.py +++ b/src/utils/app_configuration.py @@ -58,6 +58,22 @@ class AppConfiguration(): self.from_parsed = self.configuration_from_parsed() + ### SET ATTRS + self.__set_my_attr__() + + ### PRINT + if self.debug: + self.__debug_attrs__() + + def __set_my_attr__(self) -> None: + """ + Method for setting the class attributes. + + Returns + ------- + None + """ + ### SET ATTRS self.printer_name = self.from_parsed.printer_name self.port_server = int(self.from_parsed.port_server) @@ -70,7 +86,10 @@ class AppConfiguration(): self.login_user_passwd = self.from_parsed.login_user_passwd self.login_admin_email = self.from_parsed.login_admin_email self.login_admin_passwd = self.from_parsed.login_admin_passwd + self.login_api_email = self.from_parsed.login_api_email + self.login_api_passwd = self.from_parsed.login_api_passwd self.debug = self.from_parsed.debug + self.debug_disable_printing = self.from_parsed.debug_disable_printing self.verbose = self.from_parsed.verbose self.log_to_file = self.from_parsed.log_to_file self.log_file_mode = self.from_parsed.log_file_mode @@ -86,18 +105,26 @@ class AppConfiguration(): self.use_mem_db = self.from_parsed.use_mem_db self.enabled_questions = self.from_parsed.enabled_questions self.enabled_about = self.from_parsed.enabled_about + self.enabled_api = self.from_parsed.enabled_api + self.enabled_influxdb = self.from_parsed.enabled_influxdb self.enabled_print_with_options = self.from_parsed.enabled_print_with_options self.file_preview_width = int(self.from_parsed.file_preview_width) self.file_preview_height = int(self.from_parsed.file_preview_height) self.file_auto_delete_after_print = self.from_parsed.file_auto_delete_after_print - - ### PRINT - if self.debug: - self.__debug_attrs__() + self.api_token_expire_hours = self.from_parsed.api_token_expire_hours + self.influxdb_token = self.from_parsed.influxdb_token + self.influxdb_organization = self.from_parsed.influxdb_organization + self.influxdb_port = self.from_parsed.influxdb_port + self.influxdb_url = self.from_parsed.influxdb_url + self.influxdb_measurement = self.from_parsed.influxdb_measurement + self.influxdb_rotation_minutes = self.from_parsed.influxdb_rotation_minutes + self.influxdb_bucket = self.from_parsed.influxdb_bucket + self.influxdb_bucket_description = self.from_parsed.influxdb_bucket_description + self.influxdb_bucket_retention_days = self.from_parsed.influxdb_bucket_retention_days def __configuration_colors__(self) -> None: """ - Method for setting the terminal output with colors + Method for setting the terminal output with colors. Returns ------- @@ -185,6 +212,13 @@ class AppConfiguration(): default_name='DEFAULT_DEBUG', default_val=DEFAULT_VALUES.get('DEFAULT_DEBUG') ) + ### BOOLEAN: DEBUG_DISABLE_PRINTING + ret_dict['debug_disable_printing'] = self.get_env_bool( + name_env='DEBUG_DISABLE_PRINTING', + name_config='debug_disable_printing', + default_name='DEFAULT_DEBUG_DISABLE_PRINTING', + default_val=DEFAULT_VALUES.get('DEFAULT_DEBUG_DISABLE_PRINTING') + ) ### BOOLEAN: VERBOSE ret_dict['verbose'] = self.get_env_bool( name_env='VERBOSE', @@ -220,6 +254,20 @@ class AppConfiguration(): default_name='DEFAULT_ENABLED_ABOUT', default_val=DEFAULT_VALUES.get('DEFAULT_ENABLED_ABOUT') ) + ### BOOLEAN: ENABLED_API + ret_dict['enabled_api'] = self.get_env_bool( + name_env='ENABLED_API', + name_config='enabled_api', + default_name='DEFAULT_ENABLED_API', + default_val=DEFAULT_VALUES.get('DEFAULT_ENABLED_API') + ) + ### BOOLEAN: ENABLED_INFLUXDB + ret_dict['enabled_influxdb'] = self.get_env_bool( + name_env='ENABLED_INFLUXDB', + name_config='enabled_influxdb', + default_name='DEFAULT_ENABLED_INFLUXDB', + default_val=DEFAULT_VALUES.get('DEFAULT_ENABLED_INFLUXDB') + ) ### BOOLEAN: ENABLED_PRINT_WITH_OPTIONS ret_dict['enabled_print_with_options'] = self.get_env_bool( name_env='ENABLED_PRINT_WITH_OPTIONS', @@ -304,6 +352,27 @@ class AppConfiguration(): default_name='DEFAULT_LOGIN_ADMIN_PASSWD', default_val=DEFAULT_VALUES.get('DEFAULT_LOGIN_ADMIN_PASSWD') ) + ### LOGIN_API_EMAIL + ret_dict['login_api_email'] = self.get_env( + name_env='LOGIN_API_EMAIL', + name_config='login_api_email', + default_name='DEFAULT_LOGIN_API_EMAIL', + default_val=DEFAULT_VALUES.get('DEFAULT_LOGIN_API_EMAIL') + ) + ### LOGIN_API_PASSWD + ret_dict['login_api_passwd'] = self.get_env( + name_env='LOGIN_API_PASSWD', + name_config='login_api_passwd', + default_name='DEFAULT_LOGIN_API_PASSWD', + default_val=DEFAULT_VALUES.get('DEFAULT_LOGIN_API_PASSWD') + ) + ### API_TOKEN_EXPIRE_HOURS + ret_dict['api_token_expire_hours'] = self.get_env( + name_env='API_TOKEN_EXPIRE_HOURS', + name_config='api_token_expire_hours', + default_name='DEFAULT_API_TOKEN_EXPIRE_HOURS', + default_val=DEFAULT_VALUES.get('DEFAULT_API_TOKEN_EXPIRE_HOURS') + ) ### LOG_MODE ret_dict['log_file_mode'] = self.get_env( name_env='LOG_MODE', @@ -395,6 +464,69 @@ class AppConfiguration(): default_name='DEFAULT_FILE_PREVIEW_HEIGHT', default_val=DEFAULT_VALUES.get('DEFAULT_FILE_PREVIEW_HEIGHT') ) + ### INFLUXDB_TOKEN + ret_dict['influxdb_token'] = self.get_env( + name_config='influxdb_token', + name_env='INFLUXDB_TOKEN', + default_name='DEFAULT_INFLUXDB_TOKEN', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_TOKEN') + ) + ### INFLUXDB_ORGANIZATION + ret_dict['influxdb_organization'] = self.get_env( + name_config='influxdb_organization', + name_env='INFLUXDB_ORGANIZATION', + default_name='DEFAULT_INFLUXDB_ORGANIZATION', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_ORGANIZATION') + ) + ### INFLUXDB_PORT + ret_dict['influxdb_port'] = self.get_env( + name_config='influxdb_port', + name_env='INFLUXDB_PORT', + default_name='DEFAULT_INFLUXDB_PORT', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_PORT') + ) + ### INFLUXDB_URL + ret_dict['influxdb_url'] = self.get_env( + name_config='influxdb_url', + name_env='INFLUXDB_URL', + default_name='DEFAULT_INFLUXDB_URL', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_URL') + ) + ### INFLUXDB_MEASUREMENT + ret_dict['influxdb_measurement'] = self.get_env( + name_config='influxdb_measurement', + name_env='INFLUXDB_MEASUREMENT', + default_name='DEFAULT_INFLUXDB_MEASUREMENT', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_MEASUREMENT') + ) + ### INFLUXDB_ROTATION_MINUTES + ret_dict['influxdb_rotation_minutes'] = self.get_env( + name_config='influxdb_rotation_minutes', + name_env='INFLUXDB_ROTATION_MINUTES', + default_name='DEFAULT_INFLUXDB_ROTATION_MINUTES', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_ROTATION_MINUTES') + ) + ### INFLUXDB_BUCKET + ret_dict['influxdb_bucket'] = self.get_env( + name_config='influxdb_bucket', + name_env='INFLUXDB_BUCKET', + default_name='DEFAULT_INFLUXDB_BUCKET', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_BUCKET') + ) + ### INFLUXDB_BUCKET_DESCRIPTION + ret_dict['influxdb_bucket_description'] = self.get_env( + name_config='influxdb_bucket_description', + name_env='INFLUXDB_BUCKET_DESCRIPTION', + default_name='DEFAULT_INFLUXDB_BUCKET_DESCRIPTION', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_BUCKET_DESCRIPTION') + ) + ### INFLUXDB_BUCKET_RETENTION_DAYS + ret_dict['influxdb_bucket_retention_days'] = self.get_env( + name_config='influxdb_bucket_retention_days', + name_env='INFLUXDB_BUCKET_RETENTION_DAYS', + default_name='DEFAULT_INFLUXDB_BUCKET_RETENTION_DAYS', + default_val=DEFAULT_VALUES.get('DEFAULT_INFLUXDB_BUCKET_RETENTION_DAYS') + ) return ret_dict @@ -410,221 +542,326 @@ class AppConfiguration(): parser = argparse.ArgumentParser(description='c3 InfoDesk Printer') ### BOOLEAN: DEBUG parser.add_argument( - '-d', '--debug', + '--debug', help='Enable debugging information from execution.', default=self.from_env.get('debug'), action='store_true' ) + ### BOOLEAN: DEBUG + parser.add_argument( + '--debug_disable_printing', + help='Disable the printing funcionallity for debugging.', + default=self.from_env.get('debug_disable_printing'), + action='store_true' + ) ### BOOLEAN: VERBOSE parser.add_argument( - '-v', '--verbose', + '--verbose', help='Enable printing information from execution.', default=self.from_env.get('verbose'), action='store_true' ) ### BOOLEAN: LOG TO FILE parser.add_argument( - '-lf', '--log_to_file', + '--log_to_file', help='Enable writing the log to a file.', default=self.from_env.get('log_to_file'), action='store_true' ) ### BOOLEAN: USE MEM DB parser.add_argument( - '-umd', '--use_mem_db', + '--use_mem_db', help='If using the TinyDB in memory or file.', default=self.from_env.get('use_mem_db'), action='store_true' ) ### BOOLEAN: ENABLED QUESTIONS parser.add_argument( - '-eq', '--enabled_questions', + '--enabled_questions', help='If using the questions functionality.', default=self.from_env.get('enabled_questions'), action='store_true' ) ### BOOLEAN: ENABLED ABOUT parser.add_argument( - '-ea', '--enabled_about', + '--enabled_about', help='If using the about functionality.', default=self.from_env.get('enabled_about'), action='store_true' ) ### BOOLEAN: ENABLED PRINT WITH OPTIONS parser.add_argument( - '-epwf', '--enabled_print_with_options', + '--enabled_print_with_options', help='If using the functionality for printing with options.', default=self.from_env.get('enabled_print_with_options'), action='store_true' ) + ### BOOLEAN: ENABLED API + parser.add_argument( + '--enabled_api', + help='If using the API functionality.', + default=self.from_env.get('enabled_api'), + action='store_true' + ) + ### BOOLEAN: ENABLED API + parser.add_argument( + '--enabled_influxdb', + help='If using the InfluxDB functionality.', + default=self.from_env.get('enabled_influxdb'), + action='store_true' + ) ### BOOLEAN: DEFAULT FILE AUTO DELETE AFTER PRINT parser.add_argument( - '-fadap', '--file_auto_delete_after_print', + '--file_auto_delete_after_print', help='If auto deleting the file after printing.', default=self.from_env.get('file_auto_delete_after_print'), action='store_true' ) ### PATH TO UPLOAD parser.add_argument( - '-pu', '--path_to_upload', + '--path_to_upload', help='Path where the printing files should be uploaded.', default=self.from_env.get('path_to_upload'), type=str ) ### PATH TO LOG FILE parser.add_argument( - '-pl', '--path_to_log', + '--path_to_log', help='Path where the log file should be written.', default=self.from_env.get('path_to_log'), type=str ) ### PATH TO DATA parser.add_argument( - '-pd', '--path_to_data', + '--path_to_data', help='Path where the app data should be written.', default=self.from_env.get('path_to_data'), type=str ) ### PATH TO TEST FILE parser.add_argument( - '-pt', '--path_test_file', + '--path_test_file', help='Path where the test print file location.', default=self.from_env.get('path_to_test_file'), type=str ) ### SERVER PORT parser.add_argument( - '-p', '--port_server', + '--port_server', help='The port of the system', default=self.from_env.get('server_port'), type=int ) ### SERVER SECRET KEY parser.add_argument( - '-ssc', '--server_secret_key', + '--server_secret_key', help='The secret key from the server', default=self.from_env.get('server_secret_key'), type=str ) ### LOG FILE MODE parser.add_argument( - '-lfm', '--log_file_mode', + '--log_file_mode', help="Mode that the log file should be written, it can be: 'append' or 'new'.", default=self.from_env.get('log_file_mode'), type=str ) ### LOG FORMAT parser.add_argument( - '-f', '--log_format', + '--log_format', help='Log format to be used.', default=self.from_env.get('log_format'), type=str ) ### PRINTER NAME parser.add_argument( - '-pn', '--printer_name', + '--printer_name', help='Name of the printer to be used.', default=self.from_env.get('printer_name'), type=str ) ### LOGIN USER EMAIL parser.add_argument( - '-lue', '--login_user_email', + '--login_user_email', help='Email to be used for login as user for printing.', default=self.from_env.get('login_user_email'), type=str ) ### LOGIN USER PASSWORD parser.add_argument( - '-lup', '--login_user_passwd', + '--login_user_passwd', help='Password to be used for login as user for printing.', default=self.from_env.get('login_user_passwd'), type=str ) ### LOGIN ADMIN EMAIL parser.add_argument( - '-lae', '--login_admin_email', + '--login_admin_email', help='Email to be used for login as admin.', default=self.from_env.get('login_admin_email'), type=str ) ### LOGIN ADMIN PASSWORD parser.add_argument( - '-lap', '--login_admin_passwd', + '--login_admin_passwd', help='Password to be used for login as admin.', default=self.from_env.get('login_admin_passwd'), type=str ) + ### LOGIN API EMAIL + parser.add_argument( + '--login_api_email', + help='Email to be used for login as api.', + default=self.from_env.get('login_api_email'), + type=str + ) + ### LOGIN API PASSWORD + parser.add_argument( + '--login_api_passwd', + help='Password to be used for login as api.', + default=self.from_env.get('login_api_passwd'), + type=str + ) ### KEEP_ALIVE_MIN parser.add_argument( - '-ka', '--keep_alive', + '--keep_alive', help='The amount of minutes to keep the file at the server before deletion.', default=self.from_env.get('keep_file_minutes'), type=str ) ### NUM_DIGITS parser.add_argument( - '-nd', '--num_digits', + '--num_digits', help='The lenght of the generated code from the file to be printed.', default=self.from_env.get('num_digits'), type=int ) ### MAX_UPLOAD_FOLDER_BYTES parser.add_argument( - '-muf', '--max_upload_bytes_folder', + '--max_upload_bytes_folder', help='The maximum size in bytes that can be upload folder can keep.', default=self.from_env.get('max_upload_bytes_folder'), type=int ) ### MAX_UPLOAD_FILE_BYTES parser.add_argument( - '-mu', '--max_upload_bytes_file', + '--max_upload_bytes_file', help='The maximum size in bytes from a file that can be uploaded.', default=self.from_env.get('max_upload_bytes_file'), type=int ) ### MAX_UPLOAD_PDF_PAGES parser.add_argument( - '-mupg', '--max_upload_pdf_pages', + '--max_upload_pdf_pages', help='The maximum number of pages from a PDF file that can be uploaded.', default=self.from_env.get('max_upload_pdf_pages'), type=int ) ### MAX_UPLOAD_FILE_COPIES parser.add_argument( - '-mufc', '--max_upload_file_copies', + '--max_upload_file_copies', help='The maximum number of copies from a file that can be printed.', default=self.from_env.get('max_upload_file_copies'), type=int ) ### DATE_FORMAT parser.add_argument( - '-df', '--date_format', + '--date_format', help='The date format to be used handiling the system.', default=str(self.from_env.get('date_format')), type=str ) ### ALLOWED_FILE_EXTENSIONS parser.add_argument( - '-afe', '--allowed_file_extensions', + '--allowed_file_extensions', help='The allowed file extensions that the system can use.', default=str(self.from_env.get('allowed_file_extensions')), type=str ) ### FILE PREVIEW WIDTH parser.add_argument( - '-fpw', '--file_preview_width', + '--file_preview_width', help='The width at the webpage for previewing a file.', default=str(self.from_env.get('file_preview_width')), type=str ) ### FILE PREVIEW HEIGHT parser.add_argument( - '-fph', '--file_preview_height', + '--file_preview_height', help='The height at the webpage for previewing a file.', default=str(self.from_env.get('file_preview_height')), type=str ) + ### API_TOKEN_EXPIRE_HOURS + parser.add_argument( + '--api_token_expire_hours', + help='How many hours till the API token to expire.', + default=self.from_env.get('api_token_expire_hours'), + type=int + ) + ### INFLUXDB_TOKEN + parser.add_argument( + '--influxdb_token', + help='The token to be used for InfluxDB.', + default=self.from_env.get('influxdb_token'), + type=str + ) + ### INFLUXDB_ORGANIZATION + parser.add_argument( + '--influxdb_organization', + help='The organization to be used for InfluxDB.', + default=self.from_env.get('influxdb_organization'), + type=str + ) + ### INFLUXDB_PORT + parser.add_argument( + '--influxdb_port', + help='The port of the InfluxDB server.', + default=self.from_env.get('influxdb_port'), + type=str + ) + ### INFLUXDB_URL + parser.add_argument( + '--influxdb_url', + help='The URL of the InfluxDB server.', + default=self.from_env.get('influxdb_url'), + type=str + ) + ### INFLUXDB_MEASUREMENT + parser.add_argument( + '--influxdb_measurement', + help='The measurement name of the InfluxDB server.', + default=self.from_env.get('influxdb_measurement'), + type=str + ) + ### INFLUXDB_ROTATION_MINUTES + parser.add_argument( + '--influxdb_rotation_minutes', + help='how many minutes to refresh the values at the InfluxDB server.', + default=self.from_env.get('influxdb_rotation_minutes'), + type=str + ) + ### INFLUXDB_BUCKET + parser.add_argument( + '--influxdb_bucket', + help='The bucket name of the InfluxDB server.', + default=self.from_env.get('influxdb_bucket'), + type=str + ) + ### INFLUXDB_BUCKET_DESCRIPTION + parser.add_argument( + '--influxdb_bucket_description', + help='The description from the bucket of the InfluxDB server.', + default=self.from_env.get('influxdb_bucket_description'), + type=str + ) + ### INFLUXDB_BUCKET_RETENTION_DAYS + parser.add_argument( + '--influxdb_bucket_retention_days', + help='The retention days from the bucket of the InfluxDB server.', + default=self.from_env.get('influxdb_bucket_retention_days'), + type=str + ) return parser.parse_args() @@ -649,7 +886,10 @@ class AppConfiguration(): 'login_user_passwd': self.login_user_passwd, 'login_admin_email': self.login_admin_email, 'login_admin_passwd': self.login_admin_passwd, + 'login_api_email': self.login_api_email, + 'login_api_passwd': self.login_api_passwd, 'debug': self.debug, + 'debug_disable_printing': self.debug_disable_printing, 'verbose': self.verbose, 'log_to_file': self.log_to_file, 'log_file_mode': self.log_file_mode, @@ -665,10 +905,22 @@ class AppConfiguration(): 'use_mem_db': self.use_mem_db, 'enabled_questions': self.enabled_questions, 'enabled_about': self.enabled_about, + 'enabled_api': self.enabled_api, + 'enabled_influxdb': self.enabled_influxdb, 'enabled_print_with_options': self.enabled_print_with_options, 'file_preview_width': self.file_preview_width, 'file_preview_height': self.file_preview_height, - 'file_auto_delete_after_print': self.file_auto_delete_after_print + 'file_auto_delete_after_print': self.file_auto_delete_after_print, + 'api_token_expire_hours': self.api_token_expire_hours, + 'influxdb_token': self.influxdb_token, + 'influxdb_organization': self.influxdb_organization, + 'influxdb_port': self.influxdb_port, + 'influxdb_url': self.influxdb_url, + 'influxdb_measurement': self.influxdb_measurement, + 'influxdb_rotation_minutes': self.influxdb_rotation_minutes, + 'influxdb_bucket': self.influxdb_bucket, + 'influxdb_bucket_description': self.influxdb_bucket_description, + 'influxdb_bucket_retention_days': self.influxdb_bucket_retention_days, } def __debug_attrs__(self) -> None: @@ -691,7 +943,10 @@ class AppConfiguration(): print(self.color_green + "\t- login_user_passwd: " + self.color_end + f"'{self.login_user_passwd}'") print(self.color_green + "\t- login_admin_email: " + self.color_end + f"'{self.login_admin_email}'") print(self.color_green + "\t- login_admin_passwd: " + self.color_end + f"'{self.login_admin_passwd}'") + print(self.color_green + "\t- login_api_email: " + self.color_end + f"'{self.login_api_email}'") + print(self.color_green + "\t- login_api_passwd: " + self.color_end + f"'{self.login_api_passwd}'") print(self.color_green + "\t- debug: " + self.color_end + f"'{self.debug}'") + print(self.color_green + "\t- debug_disable_printing: " + self.color_end + f"'{self.debug_disable_printing}'") print(self.color_green + "\t- verbose: " + self.color_end + f"'{self.verbose}'") print(self.color_green + "\t- log_to_file: " + self.color_end + f"'{self.log_to_file}'") print(self.color_green + "\t- log_file_mode: " + self.color_end + f"'{self.log_file_mode}'") @@ -707,8 +962,20 @@ class AppConfiguration(): print(self.color_green + "\t- use_mem_db: " + self.color_end + f"'{self.use_mem_db}'") print(self.color_green + "\t- enabled_questions: " + self.color_end + f"'{self.enabled_questions}'") print(self.color_green + "\t- enabled_about: " + self.color_end + f"'{self.enabled_about}'") + print(self.color_green + "\t- enabled_api: " + self.color_end + f"'{self.enabled_api}'") + print(self.color_green + "\t- enabled_influxdb: " + self.color_end + f"'{self.enabled_influxdb}'") print(self.color_green + "\t- enabled_print_with_options: " + self.color_end + f"'{self.enabled_print_with_options}'") print(self.color_green + "\t- file_preview_width: " + self.color_end + f"'{self.file_preview_width}'") print(self.color_green + "\t- file_preview_height: " + self.color_end + f"'{self.file_preview_height}'") print(self.color_green + "\t- file_auto_delete_after_print: " + self.color_end + f"'{self.file_auto_delete_after_print}'") + print(self.color_green + "\t- api_token_expire_hours: " + self.color_end + f"'{self.api_token_expire_hours}'") + print(self.color_green + "\t- influxdb_token: " + self.color_end + f"'{self.influxdb_token}'") + print(self.color_green + "\t- influxdb_organization: " + self.color_end + f"'{self.influxdb_organization}'") + print(self.color_green + "\t- influxdb_port: " + self.color_end + f"'{self.influxdb_port}'") + print(self.color_green + "\t- influxdb_url: " + self.color_end + f"'{self.influxdb_url}'") + print(self.color_green + "\t- influxdb_measurement: " + self.color_end + f"'{self.influxdb_measurement}'") + print(self.color_green + "\t- influxdb_rotation_minutes: " + self.color_end + f"'{self.influxdb_rotation_minutes}'") + print(self.color_green + "\t- influxdb_bucket: " + self.color_end + f"'{self.influxdb_bucket}'") + print(self.color_green + "\t- influxdb_bucket_description: " + self.color_end + f"'{self.influxdb_bucket_description}'") + print(self.color_green + "\t- influxdb_bucket_retention_days: " + self.color_end + f"'{self.influxdb_bucket_retention_days}'") print("\n") diff --git a/src/utils/app_default_vals.py b/src/utils/app_default_vals.py index 5d2acd2..ead362f 100644 --- a/src/utils/app_default_vals.py +++ b/src/utils/app_default_vals.py @@ -21,7 +21,10 @@ DEFAULT_VALUES = { 'DEFAULT_LOGIN_USER_PASSWD': 'Please set the login password', 'DEFAULT_LOGIN_ADMIN_EMAIL': 'Please set the login email', 'DEFAULT_LOGIN_ADMIN_PASSWD': 'Please set the login password', + 'DEFAULT_LOGIN_API_EMAIL': 'Please set the login email', + 'DEFAULT_LOGIN_API_PASSWD': 'Please set the login password', 'DEFAULT_DEBUG': False, + 'DEFAULT_DEBUG_DISABLE_PRINTING': False, 'DEFAULT_VERBOSE': False, 'DEFAULT_LOG_TO_FILE': False, 'DEFAULT_LOG_MODE': 'new', @@ -35,10 +38,47 @@ DEFAULT_VALUES = { 'DEFAULT_USE_MEM_DB': False, 'DEFAULT_ENABLED_QUESTIONS': False, 'DEFAULT_ENABLED_ABOUT': False, + 'DEFAULT_ENABLED_API': False, + 'DEFAULT_ENABLED_INFLUXDB': False, 'DEFAULT_ENABLED_PRINT_WITH_OPTIONS': False, 'DEFAULT_FILE_PREVIEW_WIDTH': '800', 'DEFAULT_FILE_PREVIEW_HEIGHT': '600', 'DEFAULT_FILE_AUTO_DELETE_AFTER_PRINT': False, 'DEFAULT_MAX_UPLOAD_PDF_PAGES': 10, - 'DEFAULT_MAX_UPLOAD_FILE_COPIES': 5 + 'DEFAULT_MAX_UPLOAD_FILE_COPIES': 5, + 'DEFAULT_API_TOKEN_EXPIRE_HOURS': 120, + 'DEFAULT_INFLUXDB_TOKEN': 'Please set the influxdb token', + 'DEFAULT_INFLUXDB_PORT': 8086, + 'DEFAULT_INFLUXDB_URL': 'http://localhost', + 'DEFAULT_INFLUXDB_ORGANIZATION': 'c3infodesk', + 'DEFAULT_INFLUXDB_MEASUREMENT': 'app-usage', + 'DEFAULT_INFLUXDB_ROTATION_MINUTES': 2, + 'DEFAULT_INFLUXDB_BUCKET': 'c3infodesk-print', + 'DEFAULT_INFLUXDB_BUCKET_DESCRIPTION': 'Bucket used from InfoDesk at the 39c3', + 'DEFAULT_INFLUXDB_BUCKET_RETENTION_DAYS': 10, + 'DEFAULT_INFLUXDB_FIELD_NAME_UPLOADS': 'uploads', + 'DEFAULT_INFLUXDB_FIELD_NAME_FILES': 'files', + 'DEFAULT_INFLUXDB_FIELD_NAME_PRINTS': 'prints', + 'DEFAULT_INFLUXDB_FIELD_NAME_PAGES': 'pages', + 'DEFAULT_INFLUXDB_FIELD_NAME_SIZE': 'size', + 'DEFAULT_INFLUXDB_FIELD_NAME_SIMULTANEOUS_UPLOADS': 'simultaneous_uploads', + 'DEFAULT_INFLUXDB_BUCKET_LABELS': [ + { + 'name': '39c3', + 'description': '', + 'color': '#be2ee4' + }, + { + 'name': '39c3_InfoDesk_Printer', + 'description': 'InfoDesk Printer at 39c3', + 'color': '#be2ee4' + } + ], + 'DEFAULT_PRINTING_WITH_OPTIONS_VALUES': { + 'print_media': 'A4', + 'print_color': 'disable', + 'print_sides': 'single', + 'print_copies': '1', + 'print_ranges': 'all', + } } diff --git a/src/utils/app_files.py b/src/utils/app_files.py index 5d48159..66993f2 100644 --- a/src/utils/app_files.py +++ b/src/utils/app_files.py @@ -148,6 +148,13 @@ class AppFiles(): new_file_name = file_code + '___-___' + file_date + '___-___' + filename file_path = self.config.path_to_upload + '/' + new_file_name + # return { + # 'file_code': file_code, + # 'uploaded_date': file_date, + # 'original_name': filename, + # 'new_file_name': new_file_name, + # 'path': file_path + # } return { 'file_code': file_code, 'uploaded_date': file_date, @@ -191,6 +198,9 @@ class AppFiles(): ret_msg = f"The PDF exceeds the maximum allowed page count of '{self.config.max_upload_pdf_pages}'." raise Exception(ret_msg) + # File size + uploaded_file_info['size'] = file.tell() + # Add num_pages to uploaded_file_info uploaded_file_info['num_pages'] = num_pages @@ -222,9 +232,6 @@ class AppFiles(): uploaded_file_info = self._get_return_uploaded_file_info(file) - # Add num_pages to uploaded_file_info - uploaded_file_info['num_pages'] = 1 - try: file.save(uploaded_file_info.get('path')) # print("----> FILE SAVED") @@ -236,6 +243,12 @@ class AppFiles(): 'error_message': msg_err } + # File size + uploaded_file_info['size'] = file.tell() + + # Add num_pages to uploaded_file_info + uploaded_file_info['num_pages'] = 1 + logger(f"File with code: '{uploaded_file_info.get('file_code')}' saved to the Disk...") return uploaded_file_info diff --git a/src/utils/app_influxdb.py b/src/utils/app_influxdb.py new file mode 100644 index 0000000..3278334 --- /dev/null +++ b/src/utils/app_influxdb.py @@ -0,0 +1,446 @@ +#!/usr/bin/env python3 +""" + utils.app_influxdb.py file for the c3 printing system. + In this file it will be set the DB to be used at the system. +""" + +### +### DEPENDENCIES +### +import sys +from influxdb_client import InfluxDBClient, BucketRetentionRules, Point +from influxdb_client.client.write_api import SYNCHRONOUS + +### LOCAL +try: + from utils.app_logger import logger, logger_err +except ImportError as e: + print("\n\n Unable to import 'utils.app_logger.py' from the 'utils.app_influxdb.py' file from project \n\n") + sys.exit(1) + +try: + from utils.app_default_vals import DEFAULT_VALUES +except ImportError as e: + print("\n\n Unable to import 'web.routes_defaul_vals.py' from the 'utils.app_influxdb.py' file from project \n\n") + sys.exit(1) + + +class AppInfluxDB(): + """ + Class for setting the files InfluxDB of the app. + """ + + def __init__(self, config) -> None: + """ + Method for initialiazing of the AppInfluxDB class. + Sets the class variables. + + Returns + ------- + None + """ + self.config = config + + self.token = self.config.influxdb_token + self.org_name = self.config.influxdb_organization + self.bucket = self.config.influxdb_bucket + # Days * seconds + self.bucket_retention_days = self.config.influxdb_bucket_retention_days * 86400 + self.bucket_description = self.config.influxdb_bucket_description + self.measurement = self.config.influxdb_measurement + self.rotation_minutes = self.config.influxdb_rotation_minutes + self.port = self.config.influxdb_port + self.url = self.config.influxdb_url + ':' + self.config.influxdb_port + + # Set the bucket field names + self.field_name_uploads = DEFAULT_VALUES.get('DEFAULT_INFLUXDB_FIELD_NAME_UPLOADS') + self.field_name_files = DEFAULT_VALUES.get('DEFAULT_INFLUXDB_FIELD_NAME_FILES') + self.field_name_prints = DEFAULT_VALUES.get('DEFAULT_INFLUXDB_FIELD_NAME_PRINTS') + self.field_name_pages = DEFAULT_VALUES.get('DEFAULT_INFLUXDB_FIELD_NAME_PAGES') + self.field_name_size = DEFAULT_VALUES.get('DEFAULT_INFLUXDB_FIELD_NAME_SIZE') + self.field_name_simultaneous_uploads = DEFAULT_VALUES.get('DEFAULT_INFLUXDB_FIELD_NAME_SIMULTANEOUS_UPLOADS') + + self.set_client() + self.set_organization() + self.set_bucket() + self.set_labels() + + def set_client(self) -> None: + """ + Method for setting the InfluxDB client from the configuration. + + Returns + ------- + None + """ + logger("Setting the InfluxDB client...") + + try: + self.client = InfluxDBClient( + url=self.url, + token=self.token, + org=self.org_name + ) + + except Exception as e: + logger_err(f"Error setting the InfluxDB client with error: {str(e)}") + sys.exit(1) + + def set_organization(self) -> None: + """ + Method for setting the InfluxDB api_organizations from the configuration. + + Returns + ------- + None + """ + logger("Setting the InfluxDB api_organizations...") + + try: + self.api_organizations = self.client.organizations_api() + + except Exception as e: + logger_err(f"Error setting the InfluxDB 'organizations_api' with error: {str(e)}") + sys.exit(1) + + self.org_id = self.organization_check() + + def set_bucket(self) -> None: + """ + Method for setting the InfluxDB bucket from the configuration. + + Returns + ------- + None + """ + logger("Setting the InfluxDB bucket API...") + + try: + self.api_buckets = self.client.buckets_api() + + except Exception as e: + logger_err(f"Error setting the InfluxDB 'buckets_api' with error: {str(e)}") + sys.exit(1) + + self.bucket_check() + + def set_labels(self) -> None: + """ + Method for setting the InfluxDB api_lables from the configuration. + + Returns + ------- + None + """ + logger("Setting the InfluxDB api_lables...") + + try: + self.api_labels = self.client.labels_api() + + except Exception as e: + logger_err(f"Error setting the InfluxDB 'labels_api' with error: {str(e)}") + sys.exit(1) + + self.labels_check() + + ### + ### VALUES + ### + def value_update(self, field_name: str, field_value: int, tag_name=None, tag_value=None) -> None: + """ + Method to update the value of a field_name at the InfluxDb. + + Parameters + ---------- + field_name: str + The name of the field to be updated. + field_value: int + The value of the field to be updated. + + Returns + ------- + None + """ + logger(f"Updating value at the InfluxDB from '{str(field_name)}' with the value: {str(field_value)}") + + # Set Point + point = None + if tag_name and tag_value: + point = ( + Point(self.measurement) + .tag(tag_name, tag_value) + .field(field_name, field_value) + ) + else: + point = ( + Point(self.measurement) + .field(field_name, field_value) + ) + + try: + # Write to influx + write_api = self.client.write_api(write_options=SYNCHRONOUS) + write_api.write( + bucket=self.bucket, + org=self.org_name, + record=point + ) + + except Exception as e: + logger_err(f"Error updating the value for '{field_name}' bucket with error: {str(e)}") + + def value_get_last(self, field_name: str) -> int: + """ + Method to get the value of a field_name from the InfluxDb. + + Parameters + ---------- + field_name: str + The name of the field to get the last value. + + Returns + ------- + value_last: int + The last value from the the field. + """ + logger(f"Getting the value at the InfluxDB from: {str(field_name)}") + + value_last = None + query = f"""from(bucket:"{self.bucket}") + |> range(start:0) + |> filter(fn: (r) => + r._measurement == "{self.measurement}" and + r._field == "{field_name}" + ) + |> last()""" + + try: + last_data = self.client.query_api().query(query) + value_last = last_data[0].records[0]['_value'] + + except Exception as e: + logger_err(f"Error getting the last value from the bucket with error: {str(e)}") + + return value_last + + ### + ### ORGANIZATION + ### + def organization_check(self) -> str: + """ + Method to check if the default organization already exists. + + Returns + ------- + org_id: str + The organization ID. + """ + logger(f"Checkin if the organization with name: {self.org_name} already exixts...") + + founded_organizations = self.api_organizations.find_organizations() + + org_id = None + org_founded = None + for organization in founded_organizations: + if organization.name == self.org_name: + org_founded = organization + + if org_founded is not None: + org_id = org_founded.id + else: + org_id = self.organization_create() + + return org_id + + def organization_create(self) -> str: + """ + Method to create the default organization. + + Returns + ------- + org_id: str + The ID from the new created organization. + """ + logger(f"Creating the default organization with name: {self.org_name}") + + org_id = None + try: + new_org = self.api_organizations.create_organization(name=self.org_name) + org_id = new_org.id + logger(f"Created organization with name: '{new_org.name}'") + + except Exception as e: + logger_err(f"Error creating organization with error: {str(e)}") + sys.exit(1) + + return org_id + + ### + ### BUCKET + ### + def bucket_check(self) -> None: + """ + Method to check if the default bucket already exists. + + Returns + ------- + None + """ + logger(f"Checkin if the bucket with name: {self.bucket} already exixts...") + + ### Checks if the bucket exists + my_bucket = self.api_buckets.find_bucket_by_name(bucket_name=self.bucket) + + ### If it doesn't exists, create + if my_bucket is None: + self.bucket_create() + + else: + self.bucket_init_values_all() + + def bucket_create(self) -> None: + """ + Method to create the default bucket. + + Returns + ------- + None + """ + logger(f"Creating the default bucket with name: {self.bucket}") + + created_bucket = None + + ### Create bucket + try: + retention_rules = BucketRetentionRules( + type="expire", + shard_group_duration_seconds=3600, + every_seconds=self.bucket_retention_days + ) + + created_bucket = self.api_buckets.create_bucket( + bucket=None, + bucket_name=self.bucket, + org_id=None, + retention_rules=retention_rules, + description=self.bucket_description, + org=self.org_name + ) + + logger(f"Created bucket with name: '{created_bucket.name}'") + + except Exception as e: + logger_err(f"Error creating bucket with error: {str(e)}") + + ### Check if values ate empty + self.bucket_init_values_all() + + def bucket_init_values_all(self) -> None: + """ + Method to initializes all the value at the bucket if it's empty. + + Returns + ------- + None + """ + logger("Initializing all the values at the bucket if empty") + + self.bucket_init_values(field_name=self.field_name_uploads) + self.bucket_init_values(field_name=self.field_name_files) + self.bucket_init_values(field_name=self.field_name_prints) + self.bucket_init_values(field_name=self.field_name_pages) + self.bucket_init_values(field_name=self.field_name_size) + self.bucket_init_values(field_name=self.field_name_simultaneous_uploads) + + def bucket_init_values(self, field_name: str) -> None: + """ + Method to initializes a value at the bucket if it's empty. + + Parameters + ---------- + field_name: str + The name of the field to be initializaded. + + Returns + ------- + None + """ + logger(f"Initializing if not setted values for the field: {field_name}") + + query = f"""from(bucket:"{self.bucket}") + |> range(start:0) + |> filter(fn: (r) => + r._measurement == "{self.measurement}" and + r._field == "{field_name}" + ) + |> last()""" + + try: + last_data = self.client.query_api().query(query) + if len(last_data) == 0: + self.value_update(field_name=field_name, field_value=0) + + except Exception as e: + err_msg = f"Error getting/setting the first values from {field_name} at the bucket with error: {str(e)}" + logger_err(err_msg) + + ### + ### LABELS + ### + def labels_check(self) -> None: + """ + Method to check if the default labels already exists. + + Returns + ------- + None + """ + logger("Checkin if the default labels already exixts...") + + ### Get all labels + founded_labels = self.api_labels.find_labels() + + ### Check for label, if dont exist, create + label_names = [] + for label in founded_labels: + label_names.append(label.name) + + # for default_label in DEFAULT_BUCKET_LABELS: + for default_label in DEFAULT_VALUES.get('DEFAULT_INFLUXDB_BUCKET_LABELS'): + if default_label.get('name') not in label_names: + self.labels_create(default_label) + + def labels_create(self, default_label) -> None: + """ + Method to create InfluxDB bucket labels. + + Parameters + ---------- + default_label: str + The name of the label to be created. + + Returns + ------- + None + """ + ### Set vars + label_name = default_label.get('name') + properties = { + 'color': default_label.get('color'), + 'description': default_label.get('description') + } + + logger(f"Creating bucket label for: {label_name}") + + ### Create label + try: + new_label = self.api_labels.create_label( + name=label_name, + org_id=self.org_id, + properties=properties + ) + + logger(f"Created label: '{new_label.name}' with properties: '{new_label.properties}'") + + except Exception as e: + logger_err(f"Error creating label with name: {label_name} with error: {e}") diff --git a/src/utils/app_db.py b/src/utils/app_local_db.py similarity index 96% rename from src/utils/app_db.py rename to src/utils/app_local_db.py index 3023869..a9eb5d7 100644 --- a/src/utils/app_db.py +++ b/src/utils/app_local_db.py @@ -28,9 +28,9 @@ except ImportError as e: DEFAULT_NAME_DB = "db.json" -class AppDB(): +class AppLocalDB(): """ - Class for setting the files DB of the app. + Class for setting the local files DB of the app. """ def __init__(self, config) -> None: @@ -57,8 +57,6 @@ class AppDB(): logger("Setting the TinyDB from the config...") if self.config.use_mem_db: - # from tinydb.storages import JSONStorage - # from tinydb.middlewares import CachingMiddleware self.db = TinyDB(self.full_file_path_db, storage=CachingMiddleware(JSONStorage)) logger("DB setted for memory use only...") else: diff --git a/src/utils/app_printer.py b/src/utils/app_printer.py index 82ffc35..a27f285 100644 --- a/src/utils/app_printer.py +++ b/src/utils/app_printer.py @@ -36,7 +36,7 @@ class AppPrinter(): def __init__(self, config) -> None: """ - Function for initialiazing the class. + Function for initialiazing the AppPrinter class. Sets the class variables. Returns @@ -44,6 +44,7 @@ class AppPrinter(): None """ + self.config = config self.set_dict_printers_avail() self.printer_name = config.printer_name @@ -70,8 +71,13 @@ class AppPrinter(): """ logger(f"Printing from path: '{file_path}'") - conn = cups.Connection() - conn.printFile(self.printer_name, file_path, "", {}) + ### PRINT + if self.config.debug_disable_printing: + logger_warn("utils.AppPrinter.print -> printing disable") + + else: + conn = cups.Connection() + conn.printFile(self.printer_name, file_path, "", {}) def print_with_options( self, @@ -146,16 +152,15 @@ class AppPrinter(): logger_warn(err_msg) raise Exception(err_msg) - ### DEBUG - # from pprint import pp - # print("---> PRINTING") - # pp(print_options) - ### PRINT - conn = cups.Connection() - conn.printFile( - printer=self.printer_name, - filename=file_path, - title="This_have_to_be_setted_with_something", - options=print_options - ) + if self.config.debug_disable_printing: + logger_warn("utils.AppPrinter.print_with_options -> printing disable") + + else: + conn = cups.Connection() + conn.printFile( + printer=self.printer_name, + filename=file_path, + title="This_have_to_be_setted_with_something", + options=print_options + ) diff --git a/src/utils/app_usage.py b/src/utils/app_usage.py index 1ad0ca5..6cef5c1 100644 --- a/src/utils/app_usage.py +++ b/src/utils/app_usage.py @@ -8,16 +8,16 @@ ### ### DEPENDENCIES ### +# import os +# import os.path import sys -import os -import os.path import configparser ### LOCAL try: from utils.app_logger import logger except ImportError as e: - print("\n\n Unable to import 'utils.app_logger.py' from the 'web.routes.py' file from project \n\n") + print("\n\n Unable to import 'utils.app_logger.py' from the 'utils.app_usage.py' file from project \n\n") sys.exit(1) @@ -32,7 +32,7 @@ class AppUsage(): Class for setting the usage of the app. """ - def __init__(self, config) -> None: + def __init__(self, config, influxdb=None) -> None: """ Method for initialiazing the AppUsage class. Sets the class variables. @@ -50,7 +50,80 @@ class AppUsage(): self.full_file_path_usage = config.path_to_data + '/' + DEFAULT_USAGE_FILE self.usage = configparser.ConfigParser() - def get_total_files_in_folder(self) -> int: + self.influxdb = influxdb + + def update_from_upload(self, file_info) -> None: + """ + Method to update the usage from an upload. + + Parameters: + file_info: dict + The dictionary with the file information. + + Returns + ------- + None + """ + logger("Updating the usage values from an upload...") + + ### Update Uploads + self.counter_uploads_update() + ### Update Files + self.counter_files_update(update_type='upload') + ### Max simultaneous uploads + self.counter_max_simultaneous_uploaded_update() + ### Update Size + self.counter_size_update(file_info=file_info) + + def update_from_delete(self) -> None: + """ + Method to update the usage from a deletion. + + Returns + ------- + None + """ + logger("Updating the usage values from an deletion...") + + ### Update Files + self.counter_files_update(update_type='delete') + + def update_from_print(self, file_info=None) -> None: + """ + Method to update the usage from a printed file. + + Returns + ------- + None + """ + logger("Updating the usage values from a printed file...") + + self.counter_prints_update() + self.counter_pages_update(file_info) + + def remove_all_files(self) -> None: + """ + Method to remove usage from all the files on the system at the moment. + + Returns + ------- + None + """ + logger("Updating the usage values from the deletion from all files...") + + ### Set the values of the files as 0 + if self.influxdb is None: + self.usage.set('FILES', 'total', str(0)) + with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: + self.usage.write(file) + + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_files, field_value=0) + + #### + #### OLLLLLLLD + #### + def OLD_get_total_files_in_folder(self) -> int: """ Method to get the total files at the upload folder. @@ -59,10 +132,24 @@ class AppUsage(): int: The total files at the upload folder. """ - logger("Getting total files on the system...") + logger("Getting total files at the upload folder on the system...") + + # tot_files = 0 + # if self.influxdb is None: + # # tot_files = len([name for name in os.listdir(self.config.path_to_upload) if os.path.isfile(os.path.join(self.config.path_to_upload, name))]) + # tot_files = self.counter_files_get() + + # else: + # tot_files = self.influxdb_counter_files_get() + + # return tot_files + return self.counter_files_get() - return len([name for name in os.listdir(self.config.path_to_upload) if os.path.isfile(os.path.join(self.config.path_to_upload, name))]) + ### + ### COUNTER + ### + ### UPLOADS def counter_uploads_get(self) -> int: """ Method to get the total uploads from the system. @@ -72,10 +159,17 @@ class AppUsage(): int: The total uploads. """ - logger("Fetched the counter for total uploaded files on Disk...") + logger("Fetched the counter for total uploads...") - self.usage.read(self.full_file_path_usage) - return int(self.usage.get('UPLOADS', 'total')) + tot_uploads = None + if self.influxdb is None: + self.usage.read(self.full_file_path_usage) + tot_uploads = int(self.usage.get('UPLOADS', 'total')) + + else: + tot_uploads = self.influxdb.value_get_last(self.influxdb.field_name_uploads) + + return tot_uploads def counter_uploads_update(self) -> None: """ @@ -85,15 +179,67 @@ class AppUsage(): ------- None """ - logger("Get the total uploaded files on Disk...") + logger("Update the counter for total uploads...") tot_uploads = self.counter_uploads_get() + 1 - self.usage.set('UPLOADS', 'total', str(tot_uploads)) + if self.influxdb is None: + self.usage.set('UPLOADS', 'total', str(tot_uploads)) + with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: + self.usage.write(file) - with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: - self.usage.write(file) + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_uploads, field_value=tot_uploads) + ### FILES + def counter_files_get(self) -> int: + """ + Method to get the total files from the system. + + Returns + ------- + int: + The total uploads. + """ + logger("Fetched the counter for total files...") + + tot_files = None + if self.influxdb is None: + self.usage.read(self.full_file_path_usage) + tot_files = int(self.usage.get('FILES', 'total')) + + else: + tot_files = self.influxdb.value_get_last(self.influxdb.field_name_files) + + return tot_files + + def counter_files_update(self, update_type: str) -> None: + """ + Method to update the counter for total files from the system. + + Returns + ------- + None + """ + logger("Update the counter for total files...") + + files_at_the_moment = self.counter_files_get() + + tot_files = None + if update_type == 'upload': + tot_files = files_at_the_moment + 1 + elif update_type == 'delete': + tot_files = files_at_the_moment - 1 + + if self.influxdb is None: + self.usage.set('FILES', 'total', str(tot_files)) + with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: + self.usage.write(file) + + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_files, field_value=tot_files) + + ### PRINTS def counter_prints_get(self) -> int: """ Method to get the total prints from the system. @@ -105,8 +251,15 @@ class AppUsage(): """ logger("Fetched the counter for total prints...") - self.usage.read(self.full_file_path_usage) - return int(self.usage.get('PRINTS', 'total')) + tot_prints = None + if self.influxdb is None: + self.usage.read(self.full_file_path_usage) + tot_prints = int(self.usage.get('PRINTS', 'total')) + + else: + tot_prints = self.influxdb.value_get_last(self.influxdb.field_name_prints) + + return tot_prints def counter_prints_update(self) -> None: """ @@ -116,15 +269,19 @@ class AppUsage(): ------- None """ - logger("Updated the counter for total Prints...") + logger("Updated the counter for total prints...") tot_prints = self.counter_prints_get() + 1 - self.usage.set('PRINTS', 'total', str(tot_prints)) + if self.influxdb is None: + self.usage.set('PRINTS', 'total', str(tot_prints)) + with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: + self.usage.write(file) - with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: - self.usage.write(file) + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_prints, field_value=tot_prints) + ### PAGES def counter_pages_get(self) -> int: """ Method to get the total pages printed from the system. @@ -134,10 +291,17 @@ class AppUsage(): int: The total pages printed. """ - logger("Fetched the counter for total pages printed...") + logger("Fetched the counter for total pages...") + + tot_pages = None + if self.influxdb is None: + self.usage.read(self.full_file_path_usage) + tot_pages = int(self.usage.get('PAGES', 'total')) - self.usage.read(self.full_file_path_usage) - return int(self.usage.get('PAGES', 'total')) + else: + tot_pages = self.influxdb.value_get_last(self.influxdb.field_name_pages) + + return tot_pages def counter_pages_update(self, file_info) -> None: """ @@ -147,15 +311,19 @@ class AppUsage(): ------- None """ - logger("Updated the counter for total pages printed...") + logger("Updated the counter for total pages...") tot_pages = self.counter_pages_get() + file_info.get('num_pages') - self.usage.set('PAGES', 'total', str(tot_pages)) + if self.influxdb is None: + self.usage.set('PAGES', 'total', str(tot_pages)) + with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: + self.usage.write(file) - with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: - self.usage.write(file) + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_pages, field_value=tot_pages) + ### MAX SIMULTANEOUS UPLOADS def counter_max_simultaneous_uploaded_get(self) -> int: """ Method to get the maximal simultaneous uploads from the system. @@ -165,10 +333,17 @@ class AppUsage(): int: The maximal simultaneous uploads. """ - logger("Fetched the counter for total pages printed...") + logger("Fetched the counter for maximal simultaneous uploads...") - self.usage.read(self.full_file_path_usage) - return int(self.usage.get('MAX_SIMULTANEOUS_UPLOADS', 'total')) + tot_simult_uploads = None + if self.influxdb is None: + self.usage.read(self.full_file_path_usage) + tot_simult_uploads = int(self.usage.get('MAX_SIMULTANEOUS_UPLOADS', 'total')) + + else: + tot_simult_uploads = self.influxdb.value_get_last(self.influxdb.field_name_simultaneous_uploads) + + return tot_simult_uploads def counter_max_simultaneous_uploaded_update(self) -> None: """ @@ -178,16 +353,116 @@ class AppUsage(): ------- None """ - logger("Updated the counter for total pages printed...") + logger("Updated the counter for maximal simultaneous uploads...") # Get the total tot_simult = self.counter_max_simultaneous_uploaded_get() # Get the total uploaded files at the folder right now - tot_files_in_folder = self.get_total_files_in_folder() + tot_files_in_folder = self.counter_files_get() if tot_simult < tot_files_in_folder: - self.usage.set('MAX_SIMULTANEOUS_UPLOADS', 'total', str(tot_files_in_folder)) + if self.influxdb is None: + self.usage.set('MAX_SIMULTANEOUS_UPLOADS', 'total', str(tot_files_in_folder)) + with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: + self.usage.write(file) + + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_simultaneous_uploads, field_value=tot_files_in_folder) + + ### SIZE + def counter_size_get(self) -> int: + """ + Method to get the total size uploaded from the system. + + Returns + ------- + int: + The total size uploaded. + """ + logger("Fetched the counter for total files uploaded size...") + + tot_size = None + if self.influxdb is None: + self.usage.read(self.full_file_path_usage) + tot_size = int(self.usage.get('TOTAL_SIZE_UPLOAD', 'total')) + + else: + tot_size = self.influxdb.value_get_last(self.influxdb.field_name_size) + + return tot_size + + def counter_size_update(self, file_info) -> None: + """ + Method to update the counter for the total uploaded size from the system. + + Returns + ------- + None + """ + logger("Updated the counter for total size uploaded...") + + tot_size = self.counter_size_get() + file_info.get('size') + + if self.influxdb is None: + self.usage.set('TOTAL_SIZE_UPLOAD', 'total', str(tot_size)) with open(self.full_file_path_usage, 'w', encoding="utf-8") as file: self.usage.write(file) + + else: + self.influxdb.value_update(field_name=self.influxdb.field_name_size, field_value=tot_size) + + ### + ### INFLUXDB + ### + def influxdb_values_rotate(self): + """ + Method to update the counter for total uploads at the InfluxDb. + + Returns + ------- + None + """ + logger("Rotate the values on the InfluxDB...") + + ### UPLOADS + tot_uploads = self.counter_uploads_get() + self.influxdb.value_update(field_name=self.influxdb.field_name_uploads, field_value=tot_uploads) + + ### MAX SIMULTANEOUS UPLOADS + max_simultaneous_uploaded = self.counter_max_simultaneous_uploaded_get() + self.influxdb.value_update(field_name=self.influxdb.field_name_simultaneous_uploads, field_value=max_simultaneous_uploaded) + + ### FILES + tot_files = self.counter_files_get() + self.influxdb.value_update(field_name=self.influxdb.field_name_files, field_value=tot_files) + + ### PRINTS + tot_prints = self.counter_prints_get() + self.influxdb.value_update(field_name=self.influxdb.field_name_prints, field_value=tot_prints) + + ### PAGES + tot_pages = self.counter_pages_get() + self.influxdb.value_update(field_name=self.influxdb.field_name_pages, field_value=tot_pages) + + ### SIZE + tot_size = self.counter_size_get() + self.influxdb.value_update(field_name=self.influxdb.field_name_size, field_value=tot_size) + + def influxdb_values_reset(self): + """ + Method to reset all values at the InfluxDb. + + Returns + ------- + None + """ + logger("Reseting all the values on the InfluxDB...") + + self.influxdb.value_update(field_name=self.influxdb.field_name_uploads, field_value=0) + self.influxdb.value_update(field_name=self.influxdb.field_name_files, field_value=0) + self.influxdb.value_update(field_name=self.influxdb.field_name_prints, field_value=0) + self.influxdb.value_update(field_name=self.influxdb.field_name_pages, field_value=0) + self.influxdb.value_update(field_name=self.influxdb.field_name_size, field_value=0) + self.influxdb.value_update(field_name=self.influxdb.field_name_simultaneous_uploads, field_value=0) diff --git a/src/web/__init__.py b/src/web/__init__.py index f56ecd5..1800af2 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -9,6 +9,7 @@ from web.routes_user import AppRoutesUser from web.routes_protected import AppRoutesProtected from web.routes_debug import AppRoutesDebug from web.routes_question import AppRoutesQuestion +from web.routes_api import AppRoutesApi __author__ = "fejao, rot13" diff --git a/src/web/routes_api.py b/src/web/routes_api.py new file mode 100644 index 0000000..adf9a9d --- /dev/null +++ b/src/web/routes_api.py @@ -0,0 +1,752 @@ +#!/usr/bin/env python3 +""" + web.routes_api.py file for the c3 printing system. + In this file it will be set the routes for accessing the server trought API calls. +""" + +### DEBUG +# import json +import random + +### +### DEPENDENCIES +### +import sys +# from datetime import datetime, timedelta +from datetime import timedelta +from flask import request +# import flask_login +from flask_jwt_extended import create_access_token, create_refresh_token, get_jwt_identity, verify_jwt_in_request + +### LOCAL +try: + from utils.app_logger import logger, logger_err +except ImportError as e: + print("\n\n Unable to import 'utils.app_logger.py' from the 'web.routes_api.py' file from project \n\n") + sys.exit(1) + +try: + from web.routes_default_vals import DEFAULT_ROUTE_VALS +except ImportError as e: + print("\n\n Unable to import 'web.routes_defaul_vals.py' from the 'web.routes_api.py' file from project \n\n") + sys.exit(1) + + +class AppRoutesApi(): + """ + Class for the API routes of the Flask Server. + """ + + def __init__(self, config, jwt, users, usage, printer) -> None: + """ + Function for initialiazing the AppRoutesApi class. + Sets the class variables. + + Parameters + ---------- + config: utils.AppConfiguration + The config class object. + jwt: JWTManager + The JWTManager object. + users: + foo + usage: utils.AppUsage + The usage class object. + printer: utils.AppPrinter + The printer class object. + + Returns + ------- + None + """ + self.config = config + self.jwt = jwt + self.users = users + self.usage = usage + self.printer = printer + self.default_layout_admin = DEFAULT_ROUTE_VALS.get('LAYOUT_ADMIN') + # Init + self.token_access = None + self.token_refresh = None + + def set_init_tokens(self) -> None: + """ + Method for initializing the API tokens. + + Returns + ------- + None + """ + logger("Creating API Access Token...") + + email = self.config.login_api_email + + self.token_access = create_access_token( + identity=email, + expires_delta=timedelta(hours=self.config.api_token_expire_hours) + ) + + self.token_refresh = create_refresh_token( + identity=email, + expires_delta=timedelta(hours=self.config.api_token_expire_hours) + ) + + def _create_access_token(self, email) -> str: + """ + Method for creating an access token for the API. + + Returns + ------- + str: + The created access token. + """ + logger("Creating API Access Token...") + + self.token_access = create_access_token( + identity=email, + expires_delta=timedelta(hours=self.config.api_token_expire_hours) + ) + + return self.token_access + + def _create_refresh_token(self, email) -> str: + """ + Method for creating an refresh token for the API. + + Returns + ------- + str: + The created refresh token. + """ + logger("Creating API Refresh Token...") + + self.token_refresh = create_refresh_token( + identity=email, + expires_delta=timedelta(hours=self.config.api_token_expire_hours) + ) + + return self.token_refresh + + def _fetch_usage(self) -> dict: + """ + Method for getting the usage at the moment from the App. + + Returns + ------- + dict: + The dictionary with the info from the App usage. + """ + logger("Creating API Access Token...") + + return { + 'tot_uploads': self.usage.counter_uploads_get(), + 'tot_prints': self.usage.counter_prints_get(), + 'tot_pages': self.usage.counter_pages_get(), + 'tot_files': self.usage.counter_files_get(), + 'tot_size': self.usage.counter_size_get(), + 'tot_simultaneous_uploads': self.usage.counter_max_simultaneous_uploaded_get() + } + + ### /api/create-login-token + def create_login_token(self): + """ + Endpoint for render the '/api/create-login-token' end-point. + + Returns + ------- + ret_dict: dict + The dictionary with the answer from creating a login token. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api/create-login-token'") + + ### VARS + ret_dict = { + 'status_ok': False, + 'msg': 'init from ret_dict' + } + ret_code = 404 + + ### ONLY NEW TOKENS TO BE SETTED BY LOGIN + if not self.config.debug: + logger_err("Trying to create token in not a debug mode") + ret_dict = { + 'status_ok': False, + 'msg': 'Setting new tokens are disable...' + } + ret_code = 406 + + return ret_dict, ret_code + + ### GET PARAMS + email = request.authorization.parameters.get('username') + password = request.authorization.parameters.get('password') + + ### CHECK + if not email: + ret_dict = { + "status_ok": False, + "error_msg": "Request parameter not set: username" + } + ret_code = 401 + + elif not password: + ret_dict = { + "status_ok": False, + "error_msg": "Request parameter not set: password" + } + ret_code = 401 + + else: + if email != self.config.login_api_email: + ret_dict = { + "status_ok": False, + "error_msg": "Bad username" + } + ret_code = 401 + + elif password != self.config.login_api_passwd: + ret_dict = { + "status_ok": False, + "error_msg": "Bad password" + } + ret_code = 401 + + else: + ret_dict = { + 'status_ok': True, + 'message': 'Token created', + 'access_token': self._create_access_token(email), + 'expires_in_hours': self.config.api_token_expire_hours + } + ret_code = 200 + + return ret_dict, ret_code + + ### /api/create-refresh-token + def create_refresh_token(self): + """ + Endpoint for render the '/api/create-refresh-token' end-point. + + Returns + ------- + ret_dict: dict + The dictionary with the answer from creating a refresh token. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api/create-refresh-token'") + + ### VARS + ret_dict = { + 'status_ok': False, + 'msg': 'init from ret_dict' + } + ret_code = 404 + + ### Check header + try: + verify_jwt_in_request() + + except Exception as e: + ret_dict = { + 'status_ok': False, + 'error_message': f"Error accessing with message: '{e}'" + } + ret_code = 401 + + return ret_dict, ret_code + + try: + current_user = get_jwt_identity() + # refresh_token = self._create_refresh_token(email=current_user) + + ret_dict = { + 'status_ok': True, + 'message': 'Refresh token created', + # 'refresh_token': refresh_token, + 'refresh_token': self._create_refresh_token(email=current_user), + 'expires_in_hours': self.config.api_token_expire_hours + } + ret_code = 200 + except Exception as e: + # return jsonify({"msg": "Failed to refresh token"}), 400 + ret_dict = { + 'status_ok': False, + 'error_message': f"Error refreshing token with message: '{e}'" + } + ret_code = 400 + + return ret_dict, ret_code + + ### /api/refresh-token + def refresh_created_token(self): + """ + Endpoint for render the '/api/refresh-token' end-point. + + Returns + ------- + ret_dict: dict + The dictionary with the answer from refreshing a token. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api/refresh-token'") + + ### VARS + ret_dict = { + 'status_ok': False, + 'msg': 'init from ret_dict' + } + ret_code = 404 + + ### Check header + try: + # verify_jwt_in_request() + verify_jwt_in_request(refresh=True) + + except Exception as e: + ret_dict = { + 'status_ok': False, + 'error_message': f"Error accessing with message: '{e}'" + } + ret_code = 401 + + return ret_dict, ret_code + + # refresh token + try: + current_user = get_jwt_identity() + # access_token = self._create_access_token(email=current_user) + + ret_dict = { + 'status_ok': True, + 'message': 'Token refreshed', + # 'access_token': access_token, + 'access_token': self._create_access_token(email=current_user), + 'expires_in_hours': self.config.api_token_expire_hours + } + ret_code = 200 + except Exception as e: + ret_dict = { + 'status_ok': False, + 'error_message': f"Error refreshing token with message: '{e}'" + } + ret_code = 400 + + return ret_dict, ret_code + + ### /api/get-usage + def get_usage(self): + """ + Endpoint for render the '/api/get-usage' end-point. + + Returns + ------- + ret_dict: dict + The dictionary with the answer from the App usage at the moment. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api/get-usage'") + + ### VARS + ret_dict = { + 'status_ok': False, + 'msg': 'init from ret_dict' + } + ret_code = 404 + + ### Check header + try: + verify_jwt_in_request() + + except Exception as e: + ret_dict = { + 'status_ok': False, + 'error_message': f"Error accessing with message: '{e}'" + } + ret_code = 401 + + return ret_dict, ret_code + + ret_dict = { + 'status_ok': True, + 'usage': self._fetch_usage() + } + ret_code = 200 + + return ret_dict, ret_code + + ### /api/test + def test(self): + """ + Endpoint for render the '/api/test' end-point. + + Returns + ------- + ret_dict: dict + The dictionary with the answer from testing the API. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api/test'") + + ### VARS + ret_dict = { + 'status_ok': False, + 'msg': 'init from ret_dict' + } + ret_code = 404 + + ### Check header + try: + verify_jwt_in_request() + + except Exception as e: + ret_dict = { + 'status_ok': False, + 'error_message': f"Error accessing with message: '{e}'" + } + ret_code = 401 + + return ret_dict, ret_code + + ### Check user + try: + current_user = get_jwt_identity() + + ret_dict = { + 'status_ok': True, + 'message': f'Hello, {current_user}' + } + ret_code = 200 + + except Exception as e: + ret_dict = { + 'status_ok': False, + 'error_message': f"Login parameters not founded at the request, with error: '{e}'" + } + ret_code = 401 + + return ret_dict, ret_code + + ### + ### GRAFANA + ### + + # https://www.youtube.com/watch?v=lgZMRTST444 + # https://nagasudhir.blogspot.com/2024/05/json-grafana-plugin-to-fetch-api-data.html + # https://grafana.com/grafana/plugins/simpod-json-datasource/ + + # - '/' + # - '/metrics' + # - '/metric-payload-options' + # - '/query' + + ### /api/ + def grafana_home(self): + """ + Endpoint for render the '/api' end-point. + + Returns + ------- + str: + Empty string to be recognized from Graphana. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api'") + + return "", 200 + + ### /api/metrics + def grafana_metrics(self): + """ + Endpoint for render the '/api/metrics' end-point. + + Returns + ------- + ret_dict: dict + The dictionary with the answer from the App metrics at the moment. + ret_code: int + The number set for returning the response. + """ + logger("Open route for '/api/metrics'") + + ret_dict = [ + { + # Optional. If the value is empty, use the value as the label + "label": "Describe metric list", + # The value of the option. + "value": "DescribeMetricList", + # Configuration parameters of the payload. + "payloads": [ + { + # The label of the payload. If the value is empty, use the name as the label. + "label": "Namespace", + # The name of the payload. + "name": "namespace", + # If the value is select, the UI of the payload is a radio box. + # If the value is multi-select, the UI of the payload is a multi selection box; + # if the value is input, the UI of the payload is an input box; + # if the value is textarea, the UI of the payload is a multiline input box. The default is input. + "type": "select", + # Input box / selection box prompt information. + "placeholder": "Please select namespace", + # Whether to overload the metrics API after modifying the value of the payload. + "reloadMetric": True, + # Set the input / selection box width to a multiple of 8px. + "width": 10, + # If the payload type is select / multi-select, the list is the configuration of the option list. + "options": [ + { + # The label of the payload select option. + "label": "acs_mongodb", + # The label of the payload value. + "value": "acs_mongodb", + }, { + "label": "acs_rds", + "value": "acs_rds", + } + ] + }, { + "name": "metric", + "type": "select" + }, { + "name": "instanceId", + "type": "select" + } + ] + }, { + "label": "c3printer Totals", + "value": "c3printer_totals", + # Configuration parameters of the payload. + "payloads": [ + { + # The label of the payload. If the value is empty, use the name as the label. + "label": "Total ", + # The name of the payload. + "name": "usage", + # If the value is select, the UI of the payload is a radio box. + # If the value is multi-select, the UI of the payload is a multi selection box; + # if the value is input, the UI of the payload is an input box; + # if the value is textarea, the UI of the payload is a multiline input box. The default is input. + "type": "select", + # Input box / selection box prompt information. + "placeholder": "Please select usage", + # Whether to overload the metrics API after modifying the value of the payload. + "reloadMetric": True, + # Set the input / selection box width to a multiple of 8px. + "width": 10, + # If the payload type is select / multi-select, the list is the configuration of the option list. + "options": [ + { + "label": "Total Files in Folder", + "value": "tot_files_in_folder", + }, { + "label": "Total Files Uploaded", + "value": "tot_uploads" + }, { + "label": "Total Pages Printed", + "value": "tot_pages" + }, { + "label": "Maximal Simultaneous Uploads", + "value": "max_simultaneous_uploads" + }, + ] + } + ] + }, + { + "label": "Describe Metric Last", + "value": "describe_metric_last", + "payloads": [ + { + "name": "namespace", + "type": "select" + }, { + "name": "metric", + "type": "select" + }, { + "name": "instanceId", + "type": "multi-select" + } + ] + } + ] + + return ret_dict, 200 + + ### /api/metric-payload-options + def grafana_metric_payload_options(self): + """ + Endpoint for render the '/api/metric-payload-options' page. + + Returns + ------- + wrappers.Response: + The JSON and CODE from logging at the API. + """ + logger("Open route for '/api/metric-payload-options'") + + ret_dict = [ + { + "label": "Total Files in Folder", + "value": "tot_files_in_folder" + }, { + "label": "Total Files Uploaded", + "value": "tot_uploads" + }, { + "label": "Total Pages Printed", + "value": "tot_pages" + }, { + "label": "Maximal Simultaneous Uploads", + "value": "max_simultaneous_uploads" + } + ] + + return ret_dict, 200 + + ### /api/query + def grafana_query(self): + """ + Endpoint for render the '/api/query' page. + + Returns + ------- + wrappers.Response: + The JSON and CODE from logging at the API. + """ + logger("Open route for '/api/query'") + + # { + # 'app': 'dashboard', + # 'dashboardUID': 'dea6gv30fgoowf', + # 'interval': '1m', + # 'intervalMs': 60000, + # 'maxDataPoints': 925, + # 'panelId': 1, + # 'panelPluginId': 'table', + # 'range': {'from': '2025-01-16T05:42:11.941Z', + # 'raw': {'from': 'now-12h', 'to': 'now'}, + # 'to': '2025-01-16T17:42:11.941Z'}, + # 'rangeRaw': {'from': 'now-12h', 'to': 'now'}, + # 'requestId': 'SQR113', + # 'scopedVars': {'__interval': {'text': '1m', 'value': '1m'}, + # '__interval_ms': {'text': '60000', 'value': 60000}, + # '__sceneObject': {'text': '__sceneObject'}}, + # 'scopes': [], + # 'startTime': 1737049331949, + # 'targets': [{'datasource': {'type': 'simpod-json-datasource', + # 'uid': 'fea6fzbhavshsa'}, + # 'editorMode': 'code', + # 'payload': {'usage': 'tot_files_in_folder'}, + # 'refId': 'test1', + # 'target': 'c3printer_totals'}], + # 'timezone': 'browser' + # } + + ### VARS + # data_dict = None + # payload_usage = None + # ref_id = None + + target_target = None + target_payload = None + target_data = None + + ret_payload = None + + ### GET payload_usage + # usage = dict(request.data).get('usage') + + ### GET QUERY DATA + query_data = request.get_json() + # ### TIME + # time_start = datetime.strptime(query_data["range"]["from"], "%Y-%m-%dT%H:%M:%S.%fZ") + # time_end = datetime.strptime(query_data["range"]["to"], "%Y-%m-%dT%H:%M:%S.%fZ") + + response = [] + for target in query_data.get('targets'): + target_target = target.get('target') + target_payload = target.get('payload', {}) + target_data = { + 'target': target.get('refId'), + 'datapoints': [] + } + + if target_target == 'c3printer_totals': + if target_payload == 'tot_files_in_folder': + ret_payload = self.usage.counter_files_get() + + # else: + # import pdb; pdb.set_trace() + print(ret_payload) + + counter = 0 + while counter < 5: + counter += 1 + target_data['datapoints'].append( + [random.randint(100, 300), int(10 * 1000)] + ) + + response.append(target_data) + + # samplFreq = int(target_payload.get("sampling_freq", "60")) + + # data_dict = json.loads(request.data) + # for target in data_dict.get('targets'): + # if target.get('target') == 'c3printer_totals': + # payload_usage = target.get('payload').get('usage') + # ref_id = target.get('refId') + + # if payload_usage == 'tot_files_in_folder': + # import pdb; pdb.set_trace() + + # else: + # import pdb; pdb.set_trace() + # print("----> 1") + + # ### IF REQ GET + # if request.method == 'GET': + # print("wtf") + + # # from datetime import datetime + # dt_1 = datetime(2025, 1, 16, 15, 0) + # dt_2 = datetime(2025, 1, 16, 16, 0) + # dt_3 = datetime(2025, 1, 16, 17, 0) + + # # Convert to epoch time + # epoch_time = dt.timestamp() + # print(epoch_time) + + # ret_query = { + # 'target': 'test1', + # 'dataponts': [ + # [1, dt_1.timestamp()], + # [2, dt_2.timestamp()], + # [3, dt_3.timestamp()] + # ] + # } + + ############ + ############ + ############ + + # ret_query = [ + # { + # 'target': 'test1', + # 'dataponts': [ + # [1, dt_1.timestamp()], + # [2, dt_2.timestamp()], + # [3, dt_3.timestamp()] + # ] + # } + # ] + + # return ret_query, 200 + + ######### + return response, 200 diff --git a/src/web/routes_debug.py b/src/web/routes_debug.py index f6c1b4f..5e95b4f 100644 --- a/src/web/routes_debug.py +++ b/src/web/routes_debug.py @@ -30,7 +30,7 @@ class AppRoutesDebug(): Class for the user routes of the Flask Server. """ - def __init__(self, config, users, printer) -> None: + def __init__(self, config, users, printer, api=None) -> None: """ Function for initialiazing the AppRoutesDebug class. Sets the class variables. @@ -51,6 +51,7 @@ class AppRoutesDebug(): self.config = config self.users = users self.printer = printer + self.api = api self.default_layout_admin = DEFAULT_ROUTE_VALS.get('LAYOUT_ADMIN') @flask_login.login_required @@ -112,7 +113,7 @@ class AppRoutesDebug(): return redirect(url_for('home-admin')) @flask_login.login_required - def debug_admin(self): + def debug_sys(self): """ Endpoint for render the '/debug-admin' page. @@ -128,14 +129,67 @@ class AppRoutesDebug(): return "You do not have access to this page.", 403 ### GET PAGE STYLE AND VARS - default_vals = DEFAULT_ROUTE_VALS.get('DEBUG_ADMIN') + default_vals = DEFAULT_ROUTE_VALS.get('DEBUG_SYS') ### IF REQ GET if request.method == 'GET': ### RENDER return render_template( - "debug_admin.html", + "debug_sys.html", + enable_nav_link="debug-sys", + page_title=default_vals.get("page_title"), + page_texts=default_vals, + admin_layout=self.default_layout_admin, + debug=self.config.debug, + enabled_questions=self.config.enabled_questions, + enabled_about=self.config.enabled_about, + user=flask_login.current_user.id, + is_admin=flask_login.current_user.is_admin, + sys_config=self.config.get_dict_values() + ) + + @flask_login.login_required + def debug_api(self): + """ + Endpoint for render the '/debug-api' page. + + Returns + ------- + wrappers.Response: + The webpage for debugging the API. + """ + logger("Open route for '/debug-api'") + + # Check if the current user is an admin + if not flask_login.current_user.is_admin: + return "You do not have access to this page.", 403 + + ### GET PAGE STYLE AND VARS + default_vals = DEFAULT_ROUTE_VALS.get('DEBUG_API') + token_access = None + token_refresh = None + + ### GET API PARAMS + if self.api.token_access is None: + self.api.set_init_tokens() + + if self.api.token_access: + token_access = self.api.token_access + else: + token_access = 'No access token created for the API' + + if self.api.token_refresh: + token_refresh = self.api.token_refresh + else: + token_refresh = 'No refresh token created for the API' + + ### IF REQ GET + if request.method == 'GET': + + ### RENDER + return render_template( + "debug_api.html", enable_nav_link="debug-admin", page_title=default_vals.get("page_title"), page_texts=default_vals, @@ -145,5 +199,5 @@ class AppRoutesDebug(): enabled_about=self.config.enabled_about, user=flask_login.current_user.id, is_admin=flask_login.current_user.is_admin, - sys_config=self.config.get_dict_values(), + api_config={'token_access': token_access, 'token_refresh': token_refresh} ) diff --git a/src/web/routes_default_vals.py b/src/web/routes_default_vals.py index 77a58bf..d625fcc 100644 --- a/src/web/routes_default_vals.py +++ b/src/web/routes_default_vals.py @@ -24,7 +24,8 @@ DEFAULT_ROUTE_VALS['LAYOUT_ADMIN'] = { 'nav_bar_name_clean': 'Clean', 'nav_bar_name_questions': 'Most Asked Questions', 'nav_bar_name_debug_printers': 'Printer Debug', - 'nav_bar_name_debug_admin': 'System Debug', + 'nav_bar_name_debug_system': 'System Debug', + 'nav_bar_name_debug_api': 'API Debug', 'nav_bar_name_documentation': 'Documentation', 'nav_bar_name_logout': 'Logout', 'nav_bar_logo': DEFAULT_LOGO_SMALL, @@ -91,6 +92,7 @@ DEFAULT_ROUTE_VALS['HOME_ADMIN'] = { 'text_total_prints': 'Total Prints', 'text_total_pages': 'Total Pages Printed', 'text_total_files': 'Total Files at the Moment', + 'text_total_size': 'Total Uploaded Size Mb', 'text_max_simultaneous_uploaded': 'Max Simultaneous Uploads', 'text_message': 'Message', 'button_delete': 'Delete', @@ -102,23 +104,31 @@ DEFAULT_ROUTE_VALS['HOME_ADMIN'] = { ### /uploaded-list DEFAULT_ROUTE_VALS['UPLOADED_LIST'] = { 'page_title': "39c3 InfoDesk Printer Uploaded files list", - 'page_h1': "List of uploaded files", - 'text_total_files': 'Total files in the system at the moment', + 'page_h1': "List of uploaded files.", + 'page_h3': "The files onder then '{}' minutes will be deleted autoMAGICALLY.", + 'text_total_files': 'Total files in the system at the moment:', + 'text_total_folder_size': 'Total folder size in Mb at the moment:', 'text_file_code': 'File Code', 'text_file_preview': 'Preview', 'text_file_date_upload': 'Date Upload', 'text_file_original_name': 'Original Name', + 'text_file_size': 'File Size Mb', + 'text_file_pages': 'File Pages', 'button_preview': 'Preview' } ### /uploaded-clean DEFAULT_ROUTE_VALS['UPLOADED_CLEAN'] = { 'page_title': " 39c3 InfoDesk Printer Uploaded Files Clean", - 'page_h1': "List of uploaded files to be deleted", + 'page_h1': "List of uploaded files about to expire.", + 'page_h3': "The files onder then '{}' minutes will be deleted autoMAGICALLY.", + 'text_file_files_expired': 'Total Files expired:', 'text_file_code': 'File Code', - 'text_file_preview': 'Preview', + 'text_file_delete': 'Delete', 'text_file_date_upload': 'Date Upload', 'text_file_original_name': 'Original Name', + 'text_file_size': 'File Size Mb', + 'text_file_pages': 'File Pages', 'button_delete_all': 'Delete All', 'button_nuke_all': 'Nuke All Files', 'button_delete': 'Delete', @@ -184,12 +194,18 @@ DEFAULT_ROUTE_VALS['DEBUG_PRINTERS'] = { 'ret_msg_ok': "<br>Test print executed. <br>Test file at: '<b>{}</b>' should be printed at the printer '<b>{}</b>'", } -### /debug-printers -DEFAULT_ROUTE_VALS['DEBUG_ADMIN'] = { - 'page_title': " 39c3 InfoDesk Debug Admin", +### /debug-sys +DEFAULT_ROUTE_VALS['DEBUG_SYS'] = { + 'page_title': " 39c3 InfoDesk Debug Sys", 'page_h1': "Debugging the values setted on the system", } +### /debug-sys +DEFAULT_ROUTE_VALS['DEBUG_API'] = { + 'page_title': " 39c3 InfoDesk Debug API", + 'page_h1': "Debugging the values setted on the API", +} + ### ### ROUTES-QUESTIONS ### diff --git a/src/web/routes_protected.py b/src/web/routes_protected.py index e9e425e..e934142 100644 --- a/src/web/routes_protected.py +++ b/src/web/routes_protected.py @@ -27,6 +27,12 @@ except ImportError as e: print("\n\n Unable to import 'web.routes_defaul_vals.py' from the 'web.routes_protected.py' file from project \n\n") sys.exit(1) +try: + from utils.app_default_vals import DEFAULT_VALUES +except ImportError as e: + print("\n\n Unable to import 'utils.app_default_vals.py' from the 'web.routes_protected.py' file from project \n\n") + sys.exit(1) + ### ### HELPER @@ -108,7 +114,114 @@ class AppRoutesProtected(): self.users = users self.usage = usage self.default_layout_admin = DEFAULT_ROUTE_VALS.get('LAYOUT_ADMIN') + self.default_values = DEFAULT_VALUES + + def _uploaded_clean_delete(self, file) -> None: + """ + Method to call all methods for deleting a file. + + Returns + ------- + None + """ + logger(f"Cleaning/Deleting file with code: {file.get('file_code')}") + + ### DELETE FROM DB + self.db_files.file_delete(file_info=file) + ### DELETE FROM DISK + self.files.file_delete(file_info=file) + ### UPDATE USAGE + self.usage.update_from_delete() + + def _get_print_values(self, req_dict): + """ + Method to get all printing values. + + Returns + ------- + None + """ + logger("Getting all printing values...") + + default_vals = self.default_values.get('DEFAULT_PRINTING_WITH_OPTIONS_VALUES') + + ### PRINT VARS + print_media = None + print_color = None + print_sides = None + print_copies = None + print_ranges = None + + if req_dict.get('print_media') is not None: + print_media = req_dict['print_media'] + else: + print_media = default_vals.get('print_media') + + if req_dict.get('print_color') is not None: + print_color = req_dict['print_color'] + else: + print_color = default_vals.get('print_color') + + if req_dict.get('print_sides') is not None: + print_sides = req_dict['print_sides'] + else: + print_sides = default_vals.get('print_sides') + + if req_dict.get('print_copies') is not None: + print_copies = req_dict['print_copies'] + else: + print_copies = default_vals.get('print_copies') + + if req_dict.get('print_ranges') is not None: + print_ranges = req_dict['print_ranges'] + else: + print_ranges = default_vals.get('print_ranges') + + return { + 'print_media': print_media, + 'print_color': print_color, + 'print_sides': print_sides, + 'print_copies': print_copies, + 'print_ranges': print_ranges, + } + + def _get_counters_home_admin(self) -> dict: + """ + Method to get all counters for the /home-admin endpoint. + + Returns + ------- + dict: + The dictionary with all counter values. + """ + logger("Getting all counters for /home-admin...") + + return { + 'tot_uploads': self.usage.counter_uploads_get(), + 'tot_prints': self.usage.counter_prints_get(), + 'tot_pages': self.usage.counter_pages_get(), + 'tot_files_on_folder': self.usage.counter_files_get(), + 'tot_size': self.usage.counter_size_get(), + 'max_simultaneous_uploaded': self.usage.counter_max_simultaneous_uploaded_get(), + } + + def _get_counters_uploaded_list(self) -> dict: + """ + Method to get all counters for the /home-admin endpoint. + + Returns + ------- + dict: + The dictionary with all counter values. + """ + logger("Getting all counters for /home-admin...") + + return { + 'tot_uploaded_files': self.usage.counter_files_get(), + 'tot_folder_size': self.files.get_folder_bytes_size(), + } + ### (GET | POST) /home-admin @flask_login.login_required def home_admin(self) -> str: """ @@ -132,11 +245,6 @@ class AppRoutesProtected(): if 'messages' in request.args: msg_parsed = request.args['messages'] msg = get_message_sent(msg_parsed) - ### - ### WTF: find from where this is called - ### - # import pdb; pdb.set_trace() - # print("routes_protected.home_admin --> FROM REQUEST") ### FROM SESSION elif 'messages' in session.keys(): @@ -163,6 +271,9 @@ class AppRoutesProtected(): else: msg = None + ### GET COUNTERS + counter_values = self._get_counters_home_admin() + ### RENDER return render_template( 'home_admin.html', @@ -173,13 +284,15 @@ class AppRoutesProtected(): debug=self.config.debug, enabled_questions=self.config.enabled_questions, enabled_about=self.config.enabled_about, + enabled_api=self.config.enabled_api, user=flask_login.current_user.id, is_admin=flask_login.current_user.is_admin, - tot_uploads=self.usage.counter_uploads_get(), - tot_prints=self.usage.counter_prints_get(), - tot_pages=self.usage.counter_pages_get(), - tot_files_on_folder=self.usage.get_total_files_in_folder(), - max_simultaneous_uploaded=self.usage.counter_max_simultaneous_uploaded_get(), + tot_uploads=counter_values.get('tot_uploads'), + tot_prints=counter_values.get('tot_prints'), + tot_pages=counter_values.get('tot_pages'), + tot_files_on_folder=counter_values.get('tot_files_on_folder'), + tot_size=counter_values.get('tot_size'), + max_simultaneous_uploaded=counter_values.get('max_simultaneous_uploaded'), msg=msg, alert_class=alert_class, from_request=from_request, @@ -187,6 +300,7 @@ class AppRoutesProtected(): auto_delete=self.config.file_auto_delete_after_print ) + ### (GET) /uploaded-list @flask_login.login_required def uploaded_list(self) -> str: """ @@ -201,10 +315,14 @@ class AppRoutesProtected(): ### GET PAGE STYLE AND VARS default_vals = DEFAULT_ROUTE_VALS.get('UPLOADED_LIST') + default_vals['page_h3'] = default_vals.get('page_h3').format(self.config.keep_file_minutes) ### GET ALL FILES LIST all_files = self.db_files.get_all() + ### GET COUNTERS + counter_values = self._get_counters_uploaded_list() + ### RENDER return render_template( 'upload_list.html', @@ -215,13 +333,17 @@ class AppRoutesProtected(): debug=self.config.debug, enabled_questions=self.config.enabled_questions, enabled_about=self.config.enabled_about, + enabled_api=self.config.enabled_api, user=flask_login.current_user.id, is_admin=flask_login.current_user.is_admin, - # tot_uploaded_files=len(all_files), - tot_uploaded_files=self.usage.get_total_files_in_folder(), + tot_uploaded_files=counter_values.get('tot_uploaded_files'), + tot_folder_size=counter_values.get('tot_folder_size'), + # tot_uploaded_files=self.usage.counter_files_get(), + # tot_folder_size=self.files.get_folder_bytes_size(), uploaded_files=all_files ) + ### (GET | POST) /uploaded-clean --> POST -> /home-admin @flask_login.login_required def uploaded_clean(self): """ @@ -238,6 +360,7 @@ class AppRoutesProtected(): ### GET PAGE STYLE AND VARS default_vals = DEFAULT_ROUTE_VALS.get('UPLOADED_CLEAN') + default_vals['page_h3'] = default_vals.get('page_h3').format(self.config.keep_file_minutes) ### IF REQ GET if request.method == 'GET': @@ -253,6 +376,7 @@ class AppRoutesProtected(): debug=self.config.debug, enabled_questions=self.config.enabled_questions, enabled_about=self.config.enabled_about, + enabled_api=self.config.enabled_api, user=flask_login.current_user.id, is_admin=flask_login.current_user.is_admin, files_expired=files_expired @@ -266,11 +390,8 @@ class AppRoutesProtected(): clean_files_lst = json.loads(req_dict['clean_files'].replace("'", '"')) ### DELETE FILES for file in clean_files_lst: + self._uploaded_clean_delete(file) files_deleted.append(file.get('file_code')) - ### DELETE FROM DB - self.db_files.file_delete(file_info=file) - ### DELETE FROM DISK - self.files.file_delete(file_info=file) ### CREATE SESSION VAR if len(files_deleted) == 0: @@ -290,7 +411,7 @@ class AppRoutesProtected(): return ret - ### UPDATED --> !!! DISABLED PRINT + ### (POST) /file-print-options --> /home-admin @flask_login.login_required def file_print_with_options(self): """ @@ -309,31 +430,12 @@ class AppRoutesProtected(): file_info = None file_code = None file_path = None - ### - print_media = None - print_color = None - print_sides = None - print_copies = None - print_ranges = None req_dict = request.form.to_dict() if 'file_code' in req_dict.keys(): ### GET PARSED file_code = req_dict['file_code'] - if req_dict.get('print_media') is not None: - print_media = req_dict['print_media'] - - if req_dict.get('print_color') is not None: - print_color = req_dict['print_color'] - - if req_dict.get('print_sides') is not None: - print_sides = req_dict['print_sides'] - - if req_dict.get('print_copies') is not None: - print_copies = req_dict['print_copies'] - - if req_dict.get('print_ranges') is not None: - print_ranges = req_dict['print_ranges'] + print_values = self._get_print_values(req_dict) ### GET FILE try: @@ -349,13 +451,13 @@ class AppRoutesProtected(): try: self.printer.print_with_options( file_path=file_path, - media=print_media, - color=print_color, - sides=print_sides, - page_ranges=print_ranges, - copies=print_copies + media=print_values.get('print_media'), + color=print_values.get('print_color'), + sides=print_values.get('print_sides'), + page_ranges=print_values.get('print_ranges'), + copies=print_values.get('print_copies') ) - logger_info(f"PRINT - file with code: '{file_code}'...") + logger_info(f"PRINTED - file with code: '{file_code}'...") except Exception as err: err_msg = f"Error printing the test file at the path: '{file_path}' with error: '{err}'" @@ -363,28 +465,40 @@ class AppRoutesProtected(): return err_msg else: - return "NOPE" + return "NOPE", 400 - ### UPDATE PRINT COUNTER - self.usage.counter_prints_update() + ### UPDATE USAGE + self.usage.update_from_print(file_info) ### GET PAGE STYLE AND VARS default_vals = DEFAULT_ROUTE_VALS.get('FILE_PRINT_OPTIONS') - ### RETURN INFO FROM DELETED FILE - ret_dict = { - "from": "file_print", - "msg": default_vals.get('ret_msg_with_file_code').format(file_code), - } - messages = json.dumps(ret_dict) - session['messages'] = messages - session['alert_class'] = default_vals.get('alert_class') - session['from_request'] = 'file_print' - session['file_code'] = file_code + ### RETURN INFO FROM PRINTED FILE + if self.config.debug_disable_printing: + ret_dict = { + "from": "file_print", + "msg": f"DEBUG PRINTING: 'debug_disable_printing' is set to True, not printing file with code: '{file_code}'", + } + messages = json.dumps(ret_dict) + session['messages'] = messages + session['alert_class'] = 'alert-warning' + session['from_request'] = 'file_print' + session['file_code'] = file_code + + else: + ret_dict = { + "from": "file_print", + "msg": default_vals.get('ret_msg_with_file_code').format(file_code), + } + messages = json.dumps(ret_dict) + session['messages'] = messages + session['alert_class'] = default_vals.get('alert_class') + session['from_request'] = 'file_print' + session['file_code'] = file_code return redirect(url_for('home-admin')) - ### UPDATED --> !!! DISABLED PRINT + ### (POST) /file-print --> /home-admin @flask_login.login_required def file_print(self): """ @@ -440,28 +554,38 @@ class AppRoutesProtected(): else: return "NOPE" - ### UPDATE PRINT COUNTER - self.usage.counter_prints_update() - - ### UPDATE TOTAL PAGES - self.usage.counter_pages_update(file_info) + ### UPDATE USAGE + self.usage.update_from_print(file_info) ### GET PAGE STYLE AND VARS default_vals = DEFAULT_ROUTE_VALS.get('FILE_PRINT') - ### RETURN INFO FROM DELETED FILE - ret_dict = { - "from": "file_print", - "msg": default_vals.get('ret_msg_with_file_code').format(file_code), - } - messages = json.dumps(ret_dict) - session['messages'] = messages - session['alert_class'] = default_vals.get('alert_class') - session['from_request'] = 'file_print' - session['file_code'] = file_code + ### RETURN INFO FROM PRINTED FILE + if self.config.debug_disable_printing: + ret_dict = { + "from": "file_print", + "msg": f"DEBUG PRINTING: 'debug_disable_printing' is set to True, not printing file with code: '{file_code}'", + } + messages = json.dumps(ret_dict) + session['messages'] = messages + session['alert_class'] = 'alert-warning' + session['from_request'] = 'file_print' + session['file_code'] = file_code + + else: + ret_dict = { + "from": "file_print", + "msg": default_vals.get('ret_msg_with_file_code').format(file_code), + } + messages = json.dumps(ret_dict) + session['messages'] = messages + session['alert_class'] = default_vals.get('alert_class') + session['from_request'] = 'file_print' + session['file_code'] = file_code return redirect(url_for('home-admin')) + ### (POST) /file-delete --> /home-admin @flask_login.login_required def file_delete(self): """ @@ -498,6 +622,9 @@ class AppRoutesProtected(): # From DB self.db_files.file_delete(file_info=founded_file) + ### UPDATE USAGE + self.usage.update_from_delete() + else: return "NOPE" @@ -515,6 +642,7 @@ class AppRoutesProtected(): return redirect(url_for('home-admin')) + ### (POST) /file-preview @flask_login.login_required def file_preview(self): """ @@ -553,6 +681,7 @@ class AppRoutesProtected(): debug=self.config.debug, enabled_questions=self.config.enabled_questions, enabled_about=self.config.enabled_about, + enabled_api=self.config.enabled_api, user=flask_login.current_user.id, is_admin=flask_login.current_user.is_admin, max_upload_file_copies=self.config.max_upload_file_copies, @@ -567,6 +696,7 @@ class AppRoutesProtected(): return ret_preview + ### (POST) /remove-all-files --> /home-admin @flask_login.login_required def remove_all_files(self): """ @@ -597,6 +727,9 @@ class AppRoutesProtected(): logger_err(msg_err) return msg_err + ### DELETE USAGE + self.usage.remove_all_files() + ### GET PAGE STYLE AND VARS default_vals = DEFAULT_ROUTE_VALS.get('REMOVE_ALL_FILE') @@ -605,6 +738,7 @@ class AppRoutesProtected(): ### REDIRECT return redirect(url_for('home-admin')) + ### (GET) /docs/<path:filename> @flask_login.login_required def docs(self, filename): """ @@ -622,6 +756,7 @@ class AppRoutesProtected(): docs_dir = os.path.join(os.path.dirname(__file__), 'docs', 'html') return send_from_directory(directory=docs_dir, path=filename) + ### (GET) /about @flask_login.login_required def about(self): """ @@ -646,6 +781,7 @@ class AppRoutesProtected(): debug=self.config.debug, enabled_questions=self.config.enabled_questions, enabled_about=self.config.enabled_about, + enabled_api=self.config.enabled_api, user=flask_login.current_user.id, is_admin=flask_login.current_user.is_admin ) diff --git a/src/web/routes_user.py b/src/web/routes_user.py index c610e46..5642061 100644 --- a/src/web/routes_user.py +++ b/src/web/routes_user.py @@ -222,11 +222,8 @@ class AppRoutesUser(): 'error_message': msg_err } - ### UPDATE UPLOADS COUNTER - self.usage.counter_uploads_update() - - ### UPDATE MAX_SIMULTANEOUS_UPLOADS COUNTER - self.usage.counter_max_simultaneous_uploaded_update() + ### UPDATE USAGE + self.usage.update_from_upload(file_info=ret_added_file_info) ### GET PAGE STYLE AND VARS default_vals = DEFAULT_ROUTE_VALS.get('UPLOAD') diff --git a/src/web/server.py b/src/web/server.py index c750ed8..ed9b61d 100644 --- a/src/web/server.py +++ b/src/web/server.py @@ -4,13 +4,13 @@ In this file it will be set Flask server for uploading and printing files. """ - ### ### DEPENDENCIES ### import sys from flask import Flask import flask_login +from flask_jwt_extended import JWTManager ### LOCAL import web @@ -22,12 +22,6 @@ except ImportError as err: at the file 'web.server.py' file from project with error: {err}\n\n") sys.exit(1) -try: - from utils.app_usage import AppUsage -except ImportError as e: - print("\n\n Unable to import 'utils.app_usage.py' from the 'web.server.py' file from project \n\n") - sys.exit(1) - try: from utils.app_questions import AppQuestions except ImportError as e: @@ -73,7 +67,7 @@ class AppServer(): """ self._app = app - def __init__(self, config, printer, db_files, files) -> None: + def __init__(self, config, printer, db_files, files, usage) -> None: """ Method for initialiazing the FlaskServer class. Sets the class variables. @@ -87,10 +81,11 @@ class AppServer(): ------- None """ - self.db_files = db_files self.config = config self.printer = printer + self.db_files = db_files self.files = files + self.usage = usage # At the moment, only this two types of users are necessary # I didn't wanted to add an extra DB for dealing with logins... @@ -102,11 +97,15 @@ class AppServer(): self.config.login_admin_email: { 'password': self.config.login_admin_passwd, 'is_admin': True + }, + self.config.login_api_email: { + 'password': self.config.login_api_passwd, + 'is_admin': False } } - self.usage = AppUsage(self.config) - self.questions = AppQuestions(self.config) + if self.config.enabled_questions: + self.questions = AppQuestions(self.config) self.set_server() self.set_login_manager() @@ -131,16 +130,28 @@ class AppServer(): users=self.users ) + self.routes_api = None + if self.config.enabled_api: + self.routes_api = web.AppRoutesApi( + config=self.config, + jwt=self.jwt, + users=self.users, + usage=self.usage, + printer=self.printer + ) + self.routes_debug = web.AppRoutesDebug( config=self.config, users=self.users, printer=self.printer, + api=self.routes_api ) - self.routes_question = web.AppRoutesQuestion( - config=self.config, - questions=self.questions - ) + if self.config.enabled_questions: + self.routes_question = web.AppRoutesQuestion( + config=self.config, + questions=self.questions + ) self.set_routes() @@ -165,6 +176,9 @@ class AppServer(): self.login_manager = flask_login.LoginManager() self.login_manager.init_app(self.app) + ### JWT + self.jwt = JWTManager(self.app) + def set_login_manager(self) -> None: """ Method to set login manager. @@ -265,7 +279,6 @@ class AppServer(): view_func=self.routes_protected.file_print_with_options, methods=['POST'] ) - ### self.app.add_url_rule( rule='/file-preview', endpoint='file-preview', @@ -289,6 +302,59 @@ class AppServer(): view_func=self.routes_protected.docs, methods=['GET'] ) + + ############## + ############## API + ############## + + if self.config.enabled_api: + ### API - GRAPHANA + self.app.add_url_rule( + rule='/api', + view_func=self.routes_api.grafana_home, + methods=['GET'] + ) + self.app.add_url_rule( + rule='/api/metrics', + view_func=self.routes_api.grafana_metrics, + methods=['POST'] + ) + self.app.add_url_rule( + rule='/api/metric-payload-options', + view_func=self.routes_api.grafana_metric_payload_options, + methods=['POST'] + ) + self.app.add_url_rule( + rule='/api/query', + view_func=self.routes_api.grafana_query, + methods=['POST'] + ) + ### API - ENDPOINTS + self.app.add_url_rule( + rule='/api/create-login-token', + view_func=self.routes_api.create_login_token, + methods=['POST'] + ) + self.app.add_url_rule( + rule='/api/create-refresh-token', + view_func=self.routes_api.create_refresh_token, + methods=['POST'] + ) + self.app.add_url_rule( + rule='/api/refresh-token', + view_func=self.routes_api.refresh_created_token, + methods=['POST'] + ) + self.app.add_url_rule( + rule='/api/get-usage', + view_func=self.routes_api.get_usage, + methods=['GET'] + ) + self.app.add_url_rule( + rule='/api/test', + view_func=self.routes_api.test, + methods=['GET'] + ) ### DEBUG if self.config.debug: self.app.add_url_rule( @@ -298,9 +364,16 @@ class AppServer(): methods=['GET', 'POST'] ) self.app.add_url_rule( - rule='/debug-admin', - endpoint='debug-admin', - view_func=self.routes_debug.debug_admin, + rule='/debug-sys', + endpoint='debug-sys', + view_func=self.routes_debug.debug_sys, + methods=['GET'] + ) + if self.config.enabled_api: + self.app.add_url_rule( + rule='/debug-api', + endpoint='debug-api', + view_func=self.routes_debug.debug_api, methods=['GET'] ) ### QUESTIONS diff --git a/src/web/templates/debug_api.html b/src/web/templates/debug_api.html new file mode 100644 index 0000000..f3fd20f --- /dev/null +++ b/src/web/templates/debug_api.html @@ -0,0 +1,71 @@ +{% extends 'layout_admin.html' %} + +{% block content %} + +<!-- SET SITE VALUES: Please don't change the source-code but insted use the config file for it, thank you --> +{% if page_texts %} +{% set page_h1 = page_texts.get('page_h1') %} +{% endif %} + +<!-- +---- +---- DISCLAIMER +---- +At the moment, not setting all texts as variables for this web-page. +I hope that in the future, a solution for the CUPS printer drivers can be founded... +I hate HP!!! +--> + +<!-- H1 --> +{% if page_h1 %} +<h1>{{ page_h1 }}</h1> +{% else %} +<h1>PLEASE SET TEXT FOR: page_h1</h1> +{% endif %} + + +<h3> + Here is the list from the API configuration: +</h3> +<br> + +<!-- LIST API CONFIG --> +{% if api_config %} + +<table class="table" style="width:100%"> + <thead class="thead-light"> + <tr> + <!-- KEY --> + <th> + KEY + </th> + <!-- VALUE --> + <th> + VALUE + </th> + </tr> + </thead> + <tbody> + {% for key, value in api_config.items() %} + <tr> + <td> + {{ key }} + </td> + <td> + {{ value }} + </td> + </tr> + {% endfor %} + <tbody> +</table> + +{% else %} +<div class="alert alert-danger" role="alert"> + <strong>Error!</strong> + <br> + The value from 'api_config' was not parsed to the page +</div> +{% endif %} + + +{% endblock %} \ No newline at end of file diff --git a/src/web/templates/debug_admin.html b/src/web/templates/debug_sys.html similarity index 98% rename from src/web/templates/debug_admin.html rename to src/web/templates/debug_sys.html index 2846bdd..fb50576 100644 --- a/src/web/templates/debug_admin.html +++ b/src/web/templates/debug_sys.html @@ -68,7 +68,7 @@ I hate HP!!! <hr> <h3> - Here is the list: + Here is the list with the system configuration: </h3> <br> @@ -111,5 +111,4 @@ I hate HP!!! {% endif %} - {% endblock %} \ No newline at end of file diff --git a/src/web/templates/home_admin.html b/src/web/templates/home_admin.html index 970b870..441cdb6 100644 --- a/src/web/templates/home_admin.html +++ b/src/web/templates/home_admin.html @@ -9,6 +9,7 @@ {% set text_total_prints = page_texts.get('text_total_prints') %} {% set text_total_pages = page_texts.get('text_total_pages') %} {% set text_total_files = page_texts.get('text_total_files') %} +{% set text_total_size = page_texts.get('text_total_size') %} {% set text_max_simultaneous_uploaded = page_texts.get('text_max_simultaneous_uploaded') %} {% set text_message = page_texts.get('text_message') %} {% set button_delete = page_texts.get('button_delete') %} @@ -40,7 +41,7 @@ <tr> <!-- TOTAL UPLOADS --> <th scope="row"> - {% if tot_uploads %} + {% if tot_uploads > 0 or tot_uploads == 0 %} <div class="d-flex justify-content-between"> <div> {% if text_total_uploads %} @@ -61,7 +62,7 @@ </th> <!-- TOTAL PRINTS --> <th scope="row"> - {% if tot_prints %} + {% if tot_prints > 0 or tot_prints == 0 %} <div class="d-flex justify-content-between"> <div> {% if text_total_prints %} @@ -105,7 +106,7 @@ </th> <!-- TOTAL PAGES --> <th scope="row"> - {% if tot_pages %} + {% if tot_pages > 0 or tot_pages == 0 %} <div class="d-flex justify-content-between"> <div> {% if text_total_pages %} @@ -128,7 +129,7 @@ <tr> <!-- MAX SIMULT UPLOADS --> <th scope="row"> - {% if max_simultaneous_uploaded %} + {% if max_simultaneous_uploaded > 0 or max_simultaneous_uploaded == 0 %} <div class="d-flex justify-content-between"> <div> {% if text_max_simultaneous_uploaded %} @@ -151,6 +152,32 @@ <th scope="row"> </th> </tr> + <tr> + <!-- TOTAL SIZE UPLOADED --> + <th scope="row"> + {% if tot_size > 0 or tot_size == 0 %} + <div class="d-flex justify-content-between"> + <div> + {% if text_total_size %} + <b>{{ text_total_size }}</b> + {% else %} + <b>PLEASE SET TEXT FOR: text_total_size</b> + {% endif %} + </div> + <div> + <span class="my_totals badge badge-pill text-right"> + {{ (tot_size / 1048576) | round(2) }} + </span> + </div> + </div> + {% else %} + NOT PARSED -> tot_size + {% endif %} + </th> + <!-- EMPTY: I LOVE FRONTEND SHIT --> + <th scope="row"> + </th> + </tr> </tbody> </table> diff --git a/src/web/templates/layout_admin.html b/src/web/templates/layout_admin.html index 3a15fa6..2ad41b3 100644 --- a/src/web/templates/layout_admin.html +++ b/src/web/templates/layout_admin.html @@ -12,7 +12,8 @@ {% set nav_bar_name_clean = admin_layout.get('nav_bar_name_clean') %} {% set nav_bar_name_questions = admin_layout.get('nav_bar_name_questions') %} {% set nav_bar_name_debug_printers = admin_layout.get('nav_bar_name_debug_printers') %} -{% set nav_bar_name_debug_admin = admin_layout.get('nav_bar_name_debug_admin') %} +{% set nav_bar_name_debug_system = admin_layout.get('nav_bar_name_debug_system') %} +{% set nav_bar_name_debug_api = admin_layout.get('nav_bar_name_debug_api') %} {% set nav_bar_name_printer_test = admin_layout.get('nav_bar_name_printer_test') %} {% set nav_bar_name_documentation = admin_layout.get('nav_bar_name_documentation') %} {% set nav_bar_name_logout = admin_layout.get('nav_bar_name_logout') %} @@ -149,6 +150,31 @@ </li> {% endif %} {% endif %} + <!-- + ### + ### ADMIN + ### + --> + {% if is_admin %} + <!-- DEBUG-API --> + {% if enabled_api %} + {% if enable_nav_link == 'debug-api' %} + <li class="nav-item active"> + <a class="nav-link disable" href=""> + <i class="fas fa-cogs"></i> + {{ nav_bar_name_debug_api }} + </a> + </li> + {% else %} + <li class="nav-item"> + <a class="nav-link" href="{{ url_for('debug-api') }}"> + <i class="fas fa-cogs"></i> + {{ nav_bar_name_debug_api }} + </a> + </li> + {% endif %} + {% endif %} + {% endif %} <!-- ### ### DEBUG SESSION: This can only be seen if debug is enabled @@ -156,35 +182,35 @@ --> {% if debug %} {% if is_admin %} - <!-- DEBUG-PRINTERS --> - {% if enable_nav_link == 'debug-founded-printers' %} + <!-- DEBUG-SYSTEM --> + {% if enable_nav_link == 'debug-sys' %} <li class="nav-item active"> <a class="nav-link disable" href=""> - <i class="fas fa-print"></i> - {{ nav_bar_name_debug_printers }} + <i class="fas fa-cogs"></i> + {{ nav_bar_name_debug_system }} </a> </li> {% else %} <li class="nav-item"> - <a class="nav-link" href="{{ url_for('debug-printers') }}"> - <i class="fas fa-print"></i> - {{ nav_bar_name_debug_printers }} + <a class="nav-link" href="{{ url_for('debug-sys') }}"> + <i class="fas fa-cogs"></i> + {{ nav_bar_name_debug_system }} </a> </li> {% endif %} - <!-- DEBUG-SYSTEM --> - {% if enable_nav_link == 'debug-admin' %} + <!-- DEBUG-PRINTERS --> + {% if enable_nav_link == 'debug-founded-printers' %} <li class="nav-item active"> <a class="nav-link disable" href=""> - <i class="fas fa-cogs"></i> - {{ nav_bar_name_debug_admin }} + <i class="fas fa-print"></i> + {{ nav_bar_name_debug_printers }} </a> </li> {% else %} <li class="nav-item"> - <a class="nav-link" href="{{ url_for('debug-admin') }}"> - <i class="fas fa-cogs"></i> - {{ nav_bar_name_debug_admin }} + <a class="nav-link" href="{{ url_for('debug-printers') }}"> + <i class="fas fa-print"></i> + {{ nav_bar_name_debug_printers }} </a> </li> {% endif %} diff --git a/src/web/templates/upload_clean.html b/src/web/templates/upload_clean.html index fe58b4f..13d3c50 100644 --- a/src/web/templates/upload_clean.html +++ b/src/web/templates/upload_clean.html @@ -5,11 +5,15 @@ <!-- SET SITE VALUES: Please don't change the source-code but insted use the config file for it, thank you --> {% if page_texts %} {% set page_h1 = page_texts.get('page_h1') %} +{% set page_h3 = page_texts.get('page_h3') %} +{% set text_file_files_expired = page_texts.get('text_file_files_expired') %} {% set text_total_files = page_texts.get('text_total_files') %} {% set text_file_code = page_texts.get('text_file_code') %} -{% set text_file_preview = page_texts.get('text_file_preview') %} +{% set text_file_delete = page_texts.get('text_file_delete') %} {% set text_file_date_upload = page_texts.get('text_file_date_upload') %} {% set text_file_original_name = page_texts.get('text_file_original_name') %} +{% set text_file_size = page_texts.get('text_file_size') %} +{% set text_file_pages = page_texts.get('text_file_pages') %} {% set button_delete_all = page_texts.get('button_delete_all') %} {% set button_nuke_all = page_texts.get('button_nuke_all') %} {% set button_delete = page_texts.get('button_delete') %} @@ -22,18 +26,65 @@ <h1>PLEASE SET TEXT FOR: page_h1</h1> {% endif %} -<!-- BUTTON DELETE ALL--> -<form action='uploaded-clean' method='POST'> - <button class="btn btn-primary float-left" type='submit' name='clean_files' value="{{ files_expired }}"> - {% if button_delete_all %} - {{ button_delete_all }} - {% else %} - PLEASE SET TEXT FOR: button_delete_all - {% endif %} - </button> -</form> +<!-- DEBUG --> +{% if debug %} + +<div class="alert alert-danger" role="alert" style="width:50%"> + <strong>DEBUG!</strong> + <br> + <strong>Please disable debug in production!!!</strong> + <br> + <!-- USER --> + {% if user %} + <p>DEBUGGING -> Logged in as: {{ user }}</p> + <p>DEBUGGING -> Logged is admin: '{{ is_admin }}'</p> + {% endif %} +</div> + +{% endif %} + +<!-- H3 --> +{% if page_h3 %} +<h3>{{ page_h3 }}</h3> +{% else %} +<h3>PLEASE SET TEXT FOR: page_h3</h3> +{% endif %} + +<table class="table" style="width:30%"> + <tbody> + <tr> + <!-- TOTAL FILES EXPIRED --> + {% if files_expired|length > 0 or files_expired|length == 0 %} + <th> + {% if text_file_files_expired %} + {{ text_file_files_expired }} + <span class="my_totals badge badge-pill"> + {{ files_expired|length }} + </span> + {% else %} + PLEASE SET TEXT FOR -> text_file_files_expired: {{ tot_folder_size }} + {% endif %} + </th> + {% endif %} + <!-- BUTTON DELETE ALL--> + <th> + <form action='uploaded-clean' method='POST'> + <button class="btn btn-primary float-left" type='submit' name='clean_files' value="{{ files_expired }}"> + {% if button_delete_all %} + {{ button_delete_all }} + {% else %} + PLEASE SET TEXT FOR: button_delete_all + {% endif %} + </button> + </form> + </th> + </tr> + </tbody> +</table> + <!-- BUTTON NUKE ALL--> {% if is_admin %} +<br> <form action='remove-all-files' method='POST'> <button class="btn btn-danger float-right" type='submit' name='nuke_files' value="{{ files_expired }}"> {% if button_nuke_all %} @@ -47,37 +98,68 @@ </form> {% endif %} +<!-- TABLE WITH LIST OF FILES --> <table class="table" style="width:100%"> <thead class="thead-light"> <tr> <!-- FILE CODE --> {% if text_file_code %} - <th>{{ text_file_code }}</th> + <th> + <i class="fas fa-file-code"></i> + {{ text_file_code }} + </th> {% else %} <th>PLEASE SET TEXT FOR: text_file_code</th> {% endif %} - <!-- FILE PREVIEW --> - {% if text_file_preview %} - <th>{{ text_file_preview }}</th> + <!-- FILE DELETE --> + {% if text_file_delete %} + <th> + <i class="fas fa-trash"></i> + {{ text_file_delete }} + </th> {% else %} - <th>PLEASE SET TEXT FOR: text_file_preview</th> + <th>PLEASE SET TEXT FOR: text_file_delete</th> {% endif %} <!-- DATE UPLOAD --> {% if text_file_date_upload %} - <th>{{ text_file_date_upload }}</th> + <th> + <i class="fas fa-calendar"></i> + {{ text_file_date_upload }} + </th> {% else %} <th>PLEASE SET TEXT FOR: text_file_date_upload</th> {% endif %} <!-- ORIG FILE NAME --> {% if text_file_original_name %} - <th>{{ text_file_original_name }}</th> + <th> + <i class="fas fa-user-tag"></i> + {{ text_file_original_name }} + </th> {% else %} <th>PLEASE SET TEXT FOR: text_file_original_name</th> {% endif %} <!-- DEBUG --> {% if debug %} - <th>New File Name</th> - <th>File Path</th> + <th style="color:#FF0000">New File Name</th> + <th style="color:#FF0000">File Path</th> + {% endif %} + <!-- FILE SIZE --> + {% if text_file_size %} + <th> + <i class="fas fa-hdd"></i> + {{ text_file_size }} + </th> + {% else %} + <th>PLEASE SET TEXT FOR: text_file_size</th> + {% endif %} + <!-- FILE PAGES --> + {% if text_file_pages %} + <th> + <i class="fas fa-copy"></i> + {{ text_file_pages }} + </th> + {% else %} + <th>PLEASE SET TEXT FOR: text_file_pages</th> {% endif %} </tr> </thead> @@ -110,8 +192,10 @@ {% if debug %} <td>{{ value }}</td> {% endif %} + {% elif key == "size" %} + <td>{{ (value / 1048576) | round(2) }}</td> {% else %} - <td>{{ value }}</td> + <td>{{ value }}</td> {% endif %} {% endfor %} </tr> diff --git a/src/web/templates/upload_list.html b/src/web/templates/upload_list.html index b59488e..cc6566b 100644 --- a/src/web/templates/upload_list.html +++ b/src/web/templates/upload_list.html @@ -5,11 +5,15 @@ <!-- SET SITE VALUES: Please don't change the source-code but insted use the config file for it, thank you --> {% if page_texts %} {% set page_h1 = page_texts.get('page_h1') %} +{% set page_h3 = page_texts.get('page_h3') %} {% set text_total_files = page_texts.get('text_total_files') %} +{% set text_total_folder_size = page_texts.get('text_total_folder_size') %} {% set text_file_code = page_texts.get('text_file_code') %} {% set text_file_preview = page_texts.get('text_file_preview') %} {% set text_file_date_upload = page_texts.get('text_file_date_upload') %} {% set text_file_original_name = page_texts.get('text_file_original_name') %} +{% set text_file_size = page_texts.get('text_file_size') %} +{% set text_file_pages = page_texts.get('text_file_pages') %} {% set button_preview = page_texts.get('button_preview') %} {% endif %} @@ -22,7 +26,6 @@ <!-- DEBUG --> {% if debug %} - <div class="alert alert-danger" role="alert" style="width:50%"> <strong>DEBUG!</strong> <br> @@ -34,13 +37,20 @@ <p>DEBUGGING -> Logged is admin: '{{ is_admin }}'</p> {% endif %} </div> +{% endif %} +<!-- H3 --> +{% if page_h3 %} +<h3>{{ page_h3 }}</h3> +{% else %} +<h3>PLEASE SET TEXT FOR: page_h3</h3> {% endif %} -{% if tot_uploaded_files %} +<!-- TOTAL UPLOADS --> +{% if tot_uploaded_files > 0 or tot_uploaded_files == 0 %} <p> {% if text_total_files %} - {{ text_total_files }}: + {{ text_total_files }} <span class="my_totals badge badge-pill"> {{ tot_uploaded_files }} </span> @@ -50,6 +60,20 @@ </p> {% endif %} +<!-- TOTAL FOLDER SIZE --> +{% if tot_folder_size > 0 or tot_folder_size == 0 %} +<p> + {% if text_total_folder_size %} + {{ text_total_folder_size }} + <span class="my_totals badge badge-pill"> + {{ (tot_folder_size / 1048576) | round(2) }} + </span> + {% else %} + PLEASE SET TEXT FOR -> text_total_folder_size: {{ tot_folder_size }} + {% endif %} +</p> +{% endif %} + <table class="table" style="width:100%"> <thead class="thead-light"> <tr> @@ -65,7 +89,7 @@ <!-- FILE PREVIEW --> {% if text_file_preview %} <th> - <i class="fas fa-search"></i> + <i class="fas fa-image"></i> {{ text_file_preview }} </th> {% else %} @@ -94,6 +118,24 @@ <th style="color:#FF0000">New File Name</th> <th style="color:#FF0000">Full Path</th> {% endif %} + <!-- FILE SIZE --> + {% if text_file_size %} + <th> + <i class="fas fa-hdd"></i> + {{ text_file_size }} + </th> + {% else %} + <th>PLEASE SET TEXT FOR: text_file_size</th> + {% endif %} + <!-- FILE PAGES --> + {% if text_file_pages %} + <th> + <i class="fas fa-copy"></i> + {{ text_file_pages }} + </th> + {% else %} + <th>PLEASE SET TEXT FOR: text_file_pages</th> + {% endif %} </tr> </thead> <tbody> @@ -125,6 +167,8 @@ {% if debug %} <td>{{ value }}</td> {% endif %} + {% elif key == "size" %} + <td>{{ (value / 1048576) | round(2) }}</td> {% else %} <td>{{ value }}</td> {% endif %} diff --git a/uploads/429-359-943___-___2025-01-15_-_20-01-36___-___test_file_1.pdf b/uploads/429-359-943___-___2025-01-15_-_20-01-36___-___test_file_1.pdf deleted file mode 100644 index b3987e27a6680219d10144aba89575ac8470ecca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9819 zcmY!laB<T$)HCB!J-p=bp2OP?&*w5yFi^-(%Hp!I(f3KsOE1Y#Fjg>72-0`U%qdAN z(s#>AEJ<}qP0mkAwX@?YE-6Y)%;l<>6WZs?eaL{P?fqX-OYXIv+rKcoCC+EhZ*F4$ z`0R_?j_&&V>w=fFeEOv3AJ^3NKvS-vfom)Cw>4W*3sg1JIi7jSlo!NzhJ5xl3EU9K zw?=nLx!fbxZ_JFD9oK_fMM_$wx?N8x1V67&4m-e>x$hd=FNT}OR$n62*Is|D=24e? zdd*S3-!{Kap5Cp<sVMler8MNp8QpnaDUTE;=NA_}+QxsYppX5cyJ44LoX{ETYh0;$ zDNvWE=B0o<%LVcyh+$}M3X%mexlA!a!VE`9Ktsw<!O+Oe!~!{7o>o=YNI#wWqCD-( zrqoFO*O{)DG=!h0p5CM@{b-L(;UBLzM~ZTqMHQyyoZQ%%%jxOIF-3ZF>mjQpg_=)8 zw=IcD&^)V`JZV#7(4(@2yQ?D=auU70ckbB!<@(!Jk?G5}m<v>%uaUAW;`mbjz5M^~ z$7jw|)<3s?UX#A>yq}e&pt5Vqqzx_-GTkaw=4)3gw*1jnOpv-W|Cw27l$nB!JICjI z=gz&!{QnMbea;a$N5!SK=>3a>3uk>l?%X26E1Xo9Z6VhAEu{9Wdq=o~bU2Ul!&_$@ zO&^&n?MtfAseOEPRR#Mae#Lv{Qt~~2cD$R&@F-()NS|w-&zjIJ#w|MWjTYu|lHGrQ zM*o*^-P0+Mt0m~abn%mOtWGt{RqB)^y-RE?J_tR^7d+&r%=^K8SC>GDr^R8dDOy{X zEeMESqJ2%eXPMCE)<5+nn*9RYnZbEVRg)H+R~4_GV{wAHMW;p~QGEW)zShtG_4i&# ziT^(N_({*AmOni)>c&wX6M80aE_o7fud-e_bXQY~dF3RZ+P<5QpNM?gT$ET8GV5gO zdWD_+a}@q>NtvP`scgPj|Gu()bJi#Q2(7|Tf*B{)K2hEBOYl-z%sG+Zo_<9xzNdlr z)$XV8O@4c(y2D1HP{KZ0L4Q(v0)Ld>W1D`Ra}|%%d+s^r9ZWZuRQoNsY<kh<<@V~V z-1P?{?>cRpyk9B$M8>>hpFbExcl>;<$e-*}?~(aWCiw2LxbrrL4aE2Low$A?ZjW+9 zaeCi|XghVM|JTKDdzWlz(^Y1j{@7@%%Y4i8S9Inihfi?2wA*0*V%;tJe;RvJj*0&5 zN<HP<HGO{u&(-T9$t!%t>gMjW6b^kCV%K-Gs!3qs*I9QL?z=bdU2N>Zb91e&Zf(!c z&d$xuyLD@aYsQT|nUCAPeto@e&!Tm^PQ|}m9kDkn^(I%{&g;qM(!9Tt=5E{IusBRp zREK#<ld$3)olU88HmV*n|2)wwp7nZ;eBP%}lh3+|6T1tP_K9f!+-BzWNLfkz*^#L~ zx}Hotyr^N4^K=icNYBJTA)Y&Kn*ybpo*xOHRq;;b&AV65KRkrxA062&a?dgGs8`nu zfsa*z%~h(Er%k(cf4486b@+wynGEjjpQ4jn_i-5ouW$|Mp0Hz<|Cs}?&N?urm45yu z*_KgqX@kY(XC5IuWnWFrE%)A=us&&a#2NEIv727LU8~kEnl<Z*o67Z*iFwPC%3iGt zW-}7d)9?Cp@x<0zC27aIn%gR~Uh!Rw&|CL#_7PL_z3Ini9zVjhZ)K#;^flYwN69Sz z`)GoK)@dFa^RMnrmmi+5+b~6FqUI{2!}6UhU1!1s%f41FJ$<uj<Gfi}4|h&m`61-V zl|xS$&P)DSIdjpXl`h6@vsr#$II^<!IiK~>X}g^kDcbP7cK&oFx@>E=YV7qdoj#G= z<}!|4|FR$KeLW}c@gkoOpKq`nZaR37qk3<U1mAq26AVg^Qo`fKo}Xy=oT>EVw6l`% zG>graeM`e1`8>1eew8R!eEZ&Ab5*TV+gyL9_566)VPV;DwRG<kiF*oS^>4m>3RY7N zf6pHn$+!2GnCwHBr(QflSx>bS?s{kivvrBo	eT`iMchS8d%qcjHNO)Am{F{J(9V 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 -- GitLab