From 0012214f9b4758dca5064eae23cbc3cebed2d365 Mon Sep 17 00:00:00 2001 From: W13R <9070224-W13R@users.noreply.gitlab.com> Date: Sun, 15 Jan 2023 23:10:01 +0100 Subject: [PATCH 01/26] Changed some issues with the scope of psycopg cursors in some scripts --- lib/archive-tables.py | 38 ++++++---------------- lib/upgrade-db.py | 62 +++++++----------------------------- lib/verify-db-app-version.py | 40 +++++------------------ 3 files changed, 29 insertions(+), 111 deletions(-) diff --git a/lib/archive-tables.py b/lib/archive-tables.py index e698e73..a1901cc 100644 --- a/lib/archive-tables.py +++ b/lib/archive-tables.py @@ -11,65 +11,47 @@ from psycopg2 import connect # archive (copy & delete) all entries in app_order and app_registertransaction timestamp = datetime.now().strftime("%Y-%m-%d-%H%M%S") - archive_folder = Path("./archive") orders_archive_path = archive_folder / ("orders-archive-" + timestamp + ".csv") transactions_archive_path = archive_folder / ("transactions-archive-" + timestamp + ".csv") if __name__ == "__main__": - - exit_code = 0 - + exit_code = 1 + connection = connect( + user = os.environ["PGDB_USER"], + password = os.environ["PGDB_PASSWORD"], + host = os.environ["PGDB_HOST"], + port = os.environ["PGDB_PORT"], + database = os.environ["PGDB_DB"] + ) + cur = connection.cursor() try: - print(f"Starting archiving to {orders_archive_path.__str__()} and {transactions_archive_path.__str__()}...") - - connection = connect( - user = os.environ["PGDB_USER"], - password = os.environ["PGDB_PASSWORD"], - host = os.environ["PGDB_HOST"], - port = os.environ["PGDB_PORT"], - database = os.environ["PGDB_DB"] - ) - - cur = connection.cursor() - - # # # # # - # copy - with orders_archive_path.open("w") as of: cur.copy_expert( "copy (select * from app_order) to STDOUT with csv delimiter ';'", of ) - with transactions_archive_path.open("w") as tf: cur.copy_expert( "copy (select * from app_registertransaction) to STDOUT with csv delimiter ';'", tf ) - # delete - cur.execute("delete from app_order;") cur.execute("delete from app_registertransaction;") connection.commit() - # # # # # - + exit_code = 0 print("done.") - except (Error, Exception) as err: - connection.rollback() print(f"An error occured while upgrading the database at {os.environ['PGDB_HOST']}:\n{err}") exit_code = 1 - finally: - cur.close() connection.close() exit(exit_code) diff --git a/lib/upgrade-db.py b/lib/upgrade-db.py index 2bc239c..d07da87 100644 --- a/lib/upgrade-db.py +++ b/lib/upgrade-db.py @@ -14,7 +14,6 @@ from psycopg2 import errorcodes # setup or upgrade the database - def log(s, error=False): if error: print(f"{s}", file=sys.stderr) @@ -39,119 +38,80 @@ def execute_sql_statement(cursor:_cursor, connection:_connection, sql_statement) if __name__ == "__main__": - - exit_code = 0 - + exit_code = 1 + conn = connect( + user = os.environ["PGDB_USER"], + password = os.environ["PGDB_PASSWORD"], + host = os.environ["PGDB_HOST"], + port = os.environ["PGDB_PORT"], + database = os.environ["PGDB_DB"] + ) + cur = conn.cursor() try: - log("\nSetting up/upgrading database...") - - conn = connect( - user = os.environ["PGDB_USER"], - password = os.environ["PGDB_PASSWORD"], - host = os.environ["PGDB_HOST"], - port = os.environ["PGDB_PORT"], - database = os.environ["PGDB_DB"] - ) - - cur = conn.cursor() - - # # # # # - log("Not deleting register_balance. You can delete it via the Admin Panel (Globals -> register_balance), as it is no more used.") - execute_sql_statement(cur, conn, """ insert into app_global values ('global_message', 'Here you can set a global message that will be shown to every user.', 0.0, ''); """) - execute_sql_statement(cur, conn, """ insert into app_global values ('admin_info', 'Here you can set am infotext that will be displayed on the admin panel.', 0.0, ''); """) - execute_sql_statement(cur, conn, """ create or replace view app_userdeposits_view as select * from app_registertransaction where is_user_deposit = true; """) - # # # # # - - # set app_version in file and database - # database - try: - cur.execute(""" select value from application_info where key = 'app_version'; """) - result = cur.fetchone() - if result == None: - cur.execute(f""" insert into application_info values ('app_version', '{os.environ['APP_VERSION']}'); """) - conn.commit() - else: - cur.execute(f""" update application_info set value = '{os.environ['APP_VERSION']}' where key = 'app_version'; """) - conn.commit() - except Error as err: - if err.pgcode == errorcodes.UNDEFINED_TABLE: - try: - conn.rollback() - cur.execute(""" create table application_info ( key varchar(32) primary key, value text ); """) - cur.execute(f""" insert into application_info values ('app_version', '{os.environ['APP_VERSION']}'); """) - conn.commit() - except Error as err2: - log(f"An error occurred while setting app_version in table application_info: {err}", error=True) exit_code = 1 - else: - log(f"An error occurred while setting app_version in table application_info: {err}", error=True) exit_code = 1 - # file - Path("./config/db_app_version.txt").write_text(os.environ["APP_VERSION"]) + # done + exit_code = 0 log("done with db setup/upgrade.") - except (Error, Exception) as err: - log(f"An error occured while upgrading the database at {os.environ['PGDB_HOST']}:\n{err}", error=True) exit_code = 1 - finally: - cur.close() conn.close() exit(exit_code) diff --git a/lib/verify-db-app-version.py b/lib/verify-db-app-version.py index 92a7627..3fb10f9 100644 --- a/lib/verify-db-app-version.py +++ b/lib/verify-db-app-version.py @@ -15,9 +15,7 @@ from psycopg2 import errorcodes def check_file(): - db_app_version_file = Path("./config/db_app_version.txt") - if not db_app_version_file.exists(): exit(1) if not db_app_version_file.is_file(): @@ -27,78 +25,56 @@ def check_file(): def check_database(): - + connection = connect( + user = environ["PGDB_USER"], + password = environ["PGDB_PASSWORD"], + host = environ["PGDB_HOST"], + port = environ["PGDB_PORT"], + database = environ["PGDB_DB"] + ) + cur = connection.cursor() try: - - connection = connect( - user = environ["PGDB_USER"], - password = environ["PGDB_PASSWORD"], - host = environ["PGDB_HOST"], - port = environ["PGDB_PORT"], - database = environ["PGDB_DB"] - ) - - cur = connection.cursor() - # check application version in db - cur.execute(""" select value from application_info where key = 'app_version'; """) - appinfo_result = list(cur.fetchone())[0] - if appinfo_result == None: cur.close() connection.close() exit(1) - if appinfo_result != environ["APP_VERSION"]: cur.close() connection.close() exit(1) - # check rows in app_global - required_rows = [ "global_message", "admin_info" ] - cur.execute(""" select name from app_global; """) - table_global_result = list(cur.fetchall()) - cur.close() connection.close() - existing_rows = [list(row)[0] for row in table_global_result] - for r in required_rows: if not r in existing_rows: exit(1) - except Error: - cur.close() connection.close() exit(1) - except Exception as e: - print(f"An exception occured: {e}") cur.close() connection.close() exit(1) - if __name__ == "__main__": - check_file() check_database() - exit(0) -- 2.43.0 From 5572fec9c192c75211ad7de65fc8df29afa6d5a7 Mon Sep 17 00:00:00 2001 From: ChaoticByte <9070224-ChaoticByte@users.noreply.gitlab.com> Date: Sat, 11 Feb 2023 17:23:57 +0100 Subject: [PATCH 02/26] Completely re-structured the project from scratch, wrote a better bootstrap script, changed configuration format to yaml, improved Caddyfile, and more. #15 #16 #20 --- .gitignore | 29 +- README.md | 42 ++- {application/app => app}/__init__.py | 0 {application/app => app}/admin.py | 2 +- app/apps.py | 6 + .../app => app}/context_processors.py | 0 {application/app => app}/forms.py | 0 app/migrations/0001_initial.py | 267 ++++++++++++++++++ .../migrations}/__init__.py | 0 {application/app => app}/models.py | 5 +- {application/app => app}/sql_queries.py | 0 {static => app/static}/css/appform.css | 0 .../static}/css/custom_number_input.css | 0 {static => app/static}/css/history.css | 0 {static => app/static}/css/index.css | 0 {static => app/static}/css/login.css | 0 {static => app/static}/css/main.css | 0 {static => app/static}/css/statistics.css | 0 {misc/icons => app/static}/favicon.ico | Bin {misc/icons => app/static}/favicon.png | Bin {static => app/static}/js/autoreload.js | 0 .../static}/js/custom_number_input.js | 0 {static => app/static}/js/deposit.js | 0 {static => app/static}/js/logged_out.js | 0 {static => app/static}/js/login.js | 0 {static => app/static}/js/main.js | 0 {static => app/static}/js/order.js | 0 {static => app/static}/js/supply.js | 0 .../templates/admin/base_site.html | 0 .../app => app}/templates/admin/index.html | 0 .../app => app}/templates/baselayout.html | 0 .../app => app}/templates/deposit.html | 0 .../app => app}/templates/footer.html | 0 .../app => app}/templates/globalmessage.html | 0 .../app => app}/templates/history.html | 0 {application/app => app}/templates/index.html | 0 {application/app => app}/templates/order.html | 0 .../templates/registration/logged_out.html | 0 .../templates/registration/login.html | 0 .../app => app}/templates/statistics.html | 0 .../app => app}/templates/supply.html | 0 .../app => app}/templates/userpanel.html | 0 {application/app => app}/urls.py | 4 +- {application/app => app}/views.py | 54 +--- application/app/apps.py | 7 - application/app/middleware.py | 11 - application/app/tests.py | 3 - application/drinks_manager/settings.py | 179 ------------ config/config.sample.sh | 31 -- {config => data}/Caddyfile | 19 +- data/config.example.yml | 37 +++ {archive => data/logs}/.gitkeep | 0 {config => data}/tls/.gitkeep | 0 docs/Commands.md | 81 ------ docs/Configuration.md | 14 - docs/Setup.md | 110 -------- install-pip-dependencies.sh | 7 - lib/activate-devel-env.sh | 6 - lib/archive-tables.py | 57 ---- lib/auto-upgrade-db.sh | 16 -- lib/bootstrap.py | 124 -------- lib/clear-expired-sessions.sh | 7 - lib/create-admin.sh | 10 - lib/db-migrations.sh | 12 - lib/env.sh | 7 - lib/generate-secret-key.py | 30 -- lib/session-clear-scheduler.py | 47 --- lib/setup-application.sh | 16 -- lib/start-django-shell.sh | 12 - lib/upgrade-db.py | 117 -------- lib/verify-db-app-version.py | 80 ------ .../de/LC_MESSAGES/django.mo | Bin .../de/LC_MESSAGES/django.po | 0 application/manage.py => manage.py | 6 +- misc/drinks-manager.service | 25 -- misc/icons/drinksmanager-icon-1024.png | Bin 102831 -> 0 bytes misc/icons/drinksmanager-icon.src.svg | 113 -------- packages/.gitkeep | 0 profilepictures/default.svg | 28 -- logs/.gitkeep => project/__init__.py | 0 .../drinks_manager => project}/asgi.py | 6 +- project/settings.py | 160 +++++++++++ .../drinks_manager => project}/urls.py | 7 +- .../drinks_manager => project}/wsgi.py | 6 +- requirements.txt | 8 +- run.sh | 94 ------ scripts/bootstrap.py | 151 ++++++++++ scripts/setup-env.sh | 20 ++ start.sh | 11 + static/favicon.ico | Bin 44425 -> 0 bytes static/favicon.png | Bin 41586 -> 0 bytes 91 files changed, 739 insertions(+), 1345 deletions(-) rename {application/app => app}/__init__.py (100%) rename {application/app => app}/admin.py (100%) create mode 100644 app/apps.py rename {application/app => app}/context_processors.py (100%) rename {application/app => app}/forms.py (100%) create mode 100644 app/migrations/0001_initial.py rename {application/drinks_manager => app/migrations}/__init__.py (100%) rename {application/app => app}/models.py (97%) rename {application/app => app}/sql_queries.py (100%) rename {static => app/static}/css/appform.css (100%) rename {static => app/static}/css/custom_number_input.css (100%) rename {static => app/static}/css/history.css (100%) rename {static => app/static}/css/index.css (100%) rename {static => app/static}/css/login.css (100%) rename {static => app/static}/css/main.css (100%) rename {static => app/static}/css/statistics.css (100%) rename {misc/icons => app/static}/favicon.ico (100%) rename {misc/icons => app/static}/favicon.png (100%) rename {static => app/static}/js/autoreload.js (100%) rename {static => app/static}/js/custom_number_input.js (100%) rename {static => app/static}/js/deposit.js (100%) rename {static => app/static}/js/logged_out.js (100%) rename {static => app/static}/js/login.js (100%) rename {static => app/static}/js/main.js (100%) rename {static => app/static}/js/order.js (100%) rename {static => app/static}/js/supply.js (100%) rename {application/app => app}/templates/admin/base_site.html (100%) rename {application/app => app}/templates/admin/index.html (100%) rename {application/app => app}/templates/baselayout.html (100%) rename {application/app => app}/templates/deposit.html (100%) rename {application/app => app}/templates/footer.html (100%) rename {application/app => app}/templates/globalmessage.html (100%) rename {application/app => app}/templates/history.html (100%) rename {application/app => app}/templates/index.html (100%) rename {application/app => app}/templates/order.html (100%) rename {application/app => app}/templates/registration/logged_out.html (100%) rename {application/app => app}/templates/registration/login.html (100%) rename {application/app => app}/templates/statistics.html (100%) rename {application/app => app}/templates/supply.html (100%) rename {application/app => app}/templates/userpanel.html (100%) rename {application/app => app}/urls.py (91%) rename {application/app => app}/views.py (89%) delete mode 100644 application/app/apps.py delete mode 100644 application/app/middleware.py delete mode 100644 application/app/tests.py delete mode 100644 application/drinks_manager/settings.py delete mode 100644 config/config.sample.sh rename {config => data}/Caddyfile (56%) create mode 100644 data/config.example.yml rename {archive => data/logs}/.gitkeep (100%) rename {config => data}/tls/.gitkeep (100%) delete mode 100644 docs/Commands.md delete mode 100644 docs/Configuration.md delete mode 100644 docs/Setup.md delete mode 100755 install-pip-dependencies.sh delete mode 100755 lib/activate-devel-env.sh delete mode 100644 lib/archive-tables.py delete mode 100644 lib/auto-upgrade-db.sh delete mode 100644 lib/bootstrap.py delete mode 100644 lib/clear-expired-sessions.sh delete mode 100644 lib/create-admin.sh delete mode 100644 lib/db-migrations.sh delete mode 100644 lib/env.sh delete mode 100644 lib/generate-secret-key.py delete mode 100644 lib/session-clear-scheduler.py delete mode 100644 lib/setup-application.sh delete mode 100644 lib/start-django-shell.sh delete mode 100644 lib/upgrade-db.py delete mode 100644 lib/verify-db-app-version.py rename {application/locale => locales}/de/LC_MESSAGES/django.mo (100%) rename {application/locale => locales}/de/LC_MESSAGES/django.po (100%) rename application/manage.py => manage.py (80%) delete mode 100644 misc/drinks-manager.service delete mode 100644 misc/icons/drinksmanager-icon-1024.png delete mode 100644 misc/icons/drinksmanager-icon.src.svg delete mode 100644 packages/.gitkeep delete mode 100644 profilepictures/default.svg rename logs/.gitkeep => project/__init__.py (100%) rename {application/drinks_manager => project}/asgi.py (56%) create mode 100644 project/settings.py rename {application/drinks_manager => project}/urls.py (86%) rename {application/drinks_manager => project}/wsgi.py (56%) delete mode 100755 run.sh create mode 100755 scripts/bootstrap.py create mode 100755 scripts/setup-env.sh create mode 100755 start.sh delete mode 100644 static/favicon.ico delete mode 100644 static/favicon.png diff --git a/.gitignore b/.gitignore index 4f97b84..794c055 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,18 @@ -/config/* -/static/admin -/application/**/migrations/* -/archive/* -/logs/* -/packages/* -/profilepictures/* -/temp -/tmp +/data/* +/data/logs/* +/data/tls/* +/data/static/* +!/data/logs/ +!/data/logs/.gitkeep +!/data/tls/ +!/data/tls/.gitkeep +!/data/static/ +!/data/static/.gitkeep +!/data/Caddyfile +!/data/*.example.* + +/venv + __pycache__ .vscode *.pem -!/config/config.sample.sh -!/config/Caddyfile -!/config/tls/ -!/profilepictures/default.svg -!.gitkeep diff --git a/README.md b/README.md index 27df4cf..c30c6f9 100644 --- a/README.md +++ b/README.md @@ -12,20 +12,44 @@ This (exaggeration intended) most incredible piece of software is written in Pyt HTML, CSS, JS, Bash and uses Django and PostgreSQL. You have to bring your own PostgreSQL Database though. +# Getting started -## Setup, Installation, Updating and Dependencies +## System Requirements -You can find the latest releases [here](https://gitlab.com/W13R/drinks-manager/-/releases), but you should consider using Git to easily switch between versions. -For more information see [Setup](docs/Setup.md). +Beneath a `PostgreSQL` DBMS, you need the following things: +- `pg_config` (Ubuntu: `libpq-dev`, RHEL: `libpq-devel`) +- `Caddy` 2.4.3+ (HTTP Reverse Proxy & Static File Server) +- `gcc`, `gettext` +- `Python` 3.9+ + - `venv` + - `pip` +- `Python` header files (RHEL: `python3-devel`, Ubuntu: `python3-dev`) -## Configuration +## Create Environment & Install dependencies + +Run the following from the main directory: + +``` +./scripts/setup-env.sh +``` + +## Activate Venv + +**On every new session**, before running commands with manage.py or developing, you have to activate the venv: + +``` +source ./venv/bin/activate +``` + +If you see `(venv)` before your command prompt, it worked! + +## + +# Configuration see [Configuration](docs/Configuration.md) +# Usage -## Usage - -After setup, run ```./run.sh help``` to see a help text. -Start the production server with ```./run.sh server```. You can ignore the error message about the "lifespan error". -For more commands, see [Commands](docs/Commands.md). +... diff --git a/application/app/__init__.py b/app/__init__.py similarity index 100% rename from application/app/__init__.py rename to app/__init__.py diff --git a/application/app/admin.py b/app/admin.py similarity index 100% rename from application/app/admin.py rename to app/admin.py index 4234240..5cab141 100644 --- a/application/app/admin.py +++ b/app/admin.py @@ -15,6 +15,7 @@ from .forms import CustomDrinkForm from .forms import CustomGlobalForm from .forms import CustomRegisterTransactionForm + # Admin Site class CustomAdminSite(admin.AdminSite): @@ -100,7 +101,6 @@ class CustomRegisterAdmin(admin.ModelAdmin): self.message_user(request, f"Revoked {queryset.count()} supplies.") delete_selected_new.short_description = "Revoke selected transactions" - adminSite.register(Register, CustomRegisterAdmin) diff --git a/app/apps.py b/app/apps.py new file mode 100644 index 0000000..bcfe39b --- /dev/null +++ b/app/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AppConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "app" diff --git a/application/app/context_processors.py b/app/context_processors.py similarity index 100% rename from application/app/context_processors.py rename to app/context_processors.py diff --git a/application/app/forms.py b/app/forms.py similarity index 100% rename from application/app/forms.py rename to app/forms.py diff --git a/app/migrations/0001_initial.py b/app/migrations/0001_initial.py new file mode 100644 index 0000000..71ead05 --- /dev/null +++ b/app/migrations/0001_initial.py @@ -0,0 +1,267 @@ +# Generated by Django 4.1.6 on 2023-02-11 15:24 + +from django.conf import settings +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + initial = True + + dependencies = [ + ("auth", "0012_alter_user_first_name_max_length"), + ] + + operations = [ + migrations.CreateModel( + name="User", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + error_messages={ + "unique": "A user with that username already exists." + }, + help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", + max_length=150, + unique=True, + validators=[ + django.contrib.auth.validators.UnicodeUsernameValidator() + ], + verbose_name="username", + ), + ), + ( + "first_name", + models.CharField( + blank=True, max_length=150, verbose_name="first name" + ), + ), + ( + "last_name", + models.CharField( + blank=True, max_length=150, verbose_name="last name" + ), + ), + ( + "email", + models.EmailField( + blank=True, max_length=254, verbose_name="email address" + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="date joined" + ), + ), + ( + "balance", + models.DecimalField(decimal_places=2, default=0.0, max_digits=8), + ), + ( + "allow_order_with_negative_balance", + models.BooleanField(default=False), + ), + ( + "profile_picture_filename", + models.CharField(default="default.svg", max_length=25), + ), + ("allowed_to_supply", models.BooleanField(default=False)), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), + ), + ], + options={ + "verbose_name": "user", + "verbose_name_plural": "users", + "abstract": False, + }, + managers=[ + ("objects", django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name="Drink", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("product_name", models.CharField(max_length=64)), + ( + "content_litres", + models.DecimalField(decimal_places=3, default=0.5, max_digits=6), + ), + ( + "price", + models.DecimalField(decimal_places=2, default=0.0, max_digits=6), + ), + ("available", models.PositiveIntegerField(default=0)), + ("deleted", models.BooleanField(default=False)), + ("do_not_count", models.BooleanField(default=False)), + ], + ), + migrations.CreateModel( + name="Global", + fields=[ + ( + "name", + models.CharField( + max_length=42, primary_key=True, serialize=False, unique=True + ), + ), + ("comment", models.TextField()), + ("value_float", models.FloatField(default=0.0)), + ("value_string", models.TextField()), + ], + ), + migrations.CreateModel( + name="RegisterTransaction", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "transaction_sum", + models.DecimalField(decimal_places=2, default=0.0, max_digits=6), + ), + ( + "old_transaction_sum", + models.DecimalField(decimal_places=2, default=0.0, max_digits=6), + ), + ("datetime", models.DateTimeField(default=django.utils.timezone.now)), + ("is_user_deposit", models.BooleanField(default=False)), + ("comment", models.TextField(default=" ")), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "verbose_name": "transaction", + "verbose_name_plural": "transactions", + }, + ), + migrations.CreateModel( + name="Order", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("datetime", models.DateTimeField(default=django.utils.timezone.now)), + ("amount", models.PositiveIntegerField(default=1, editable=False)), + ("product_name", models.CharField(editable=False, max_length=64)), + ( + "price_sum", + models.DecimalField( + decimal_places=2, default=0, editable=False, max_digits=6 + ), + ), + ( + "content_litres", + models.DecimalField( + decimal_places=3, default=0, editable=False, max_digits=6 + ), + ), + ( + "drink", + models.ForeignKey( + limit_choices_to=models.Q(("available__gt", 0)), + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="app.drink", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/application/drinks_manager/__init__.py b/app/migrations/__init__.py similarity index 100% rename from application/drinks_manager/__init__.py rename to app/migrations/__init__.py diff --git a/application/app/models.py b/app/models.py similarity index 97% rename from application/app/models.py rename to app/models.py index a3bb11c..3f4f3d1 100644 --- a/application/app/models.py +++ b/app/models.py @@ -2,7 +2,6 @@ from django.db import models from django.conf import settings from django.contrib.auth.models import AbstractUser -from django_currentuser.db.models import CurrentUserField from django.forms import ValidationError from django.utils import timezone @@ -62,7 +61,7 @@ class RegisterTransaction(models.Model): datetime = models.DateTimeField(default=timezone.now) is_user_deposit = models.BooleanField(default=False) comment = models.TextField(default=" ") - user = CurrentUserField() + user = models.ForeignKey(User, on_delete=models.CASCADE) def save(self, *args, **kwargs): if self._state.adding: @@ -100,7 +99,7 @@ class Order(models.Model): null=True, limit_choices_to=models.Q(available__gt=0) # Query only those drinks with a availability greater than (gt) 0 ) - user = CurrentUserField() + user = models.ForeignKey(User, on_delete=models.CASCADE) datetime = models.DateTimeField(default=timezone.now) amount = models.PositiveIntegerField(default=1, editable=False) diff --git a/application/app/sql_queries.py b/app/sql_queries.py similarity index 100% rename from application/app/sql_queries.py rename to app/sql_queries.py diff --git a/static/css/appform.css b/app/static/css/appform.css similarity index 100% rename from static/css/appform.css rename to app/static/css/appform.css diff --git a/static/css/custom_number_input.css b/app/static/css/custom_number_input.css similarity index 100% rename from static/css/custom_number_input.css rename to app/static/css/custom_number_input.css diff --git a/static/css/history.css b/app/static/css/history.css similarity index 100% rename from static/css/history.css rename to app/static/css/history.css diff --git a/static/css/index.css b/app/static/css/index.css similarity index 100% rename from static/css/index.css rename to app/static/css/index.css diff --git a/static/css/login.css b/app/static/css/login.css similarity index 100% rename from static/css/login.css rename to app/static/css/login.css diff --git a/static/css/main.css b/app/static/css/main.css similarity index 100% rename from static/css/main.css rename to app/static/css/main.css diff --git a/static/css/statistics.css b/app/static/css/statistics.css similarity index 100% rename from static/css/statistics.css rename to app/static/css/statistics.css diff --git a/misc/icons/favicon.ico b/app/static/favicon.ico similarity index 100% rename from misc/icons/favicon.ico rename to app/static/favicon.ico diff --git a/misc/icons/favicon.png b/app/static/favicon.png similarity index 100% rename from misc/icons/favicon.png rename to app/static/favicon.png diff --git a/static/js/autoreload.js b/app/static/js/autoreload.js similarity index 100% rename from static/js/autoreload.js rename to app/static/js/autoreload.js diff --git a/static/js/custom_number_input.js b/app/static/js/custom_number_input.js similarity index 100% rename from static/js/custom_number_input.js rename to app/static/js/custom_number_input.js diff --git a/static/js/deposit.js b/app/static/js/deposit.js similarity index 100% rename from static/js/deposit.js rename to app/static/js/deposit.js diff --git a/static/js/logged_out.js b/app/static/js/logged_out.js similarity index 100% rename from static/js/logged_out.js rename to app/static/js/logged_out.js diff --git a/static/js/login.js b/app/static/js/login.js similarity index 100% rename from static/js/login.js rename to app/static/js/login.js diff --git a/static/js/main.js b/app/static/js/main.js similarity index 100% rename from static/js/main.js rename to app/static/js/main.js diff --git a/static/js/order.js b/app/static/js/order.js similarity index 100% rename from static/js/order.js rename to app/static/js/order.js diff --git a/static/js/supply.js b/app/static/js/supply.js similarity index 100% rename from static/js/supply.js rename to app/static/js/supply.js diff --git a/application/app/templates/admin/base_site.html b/app/templates/admin/base_site.html similarity index 100% rename from application/app/templates/admin/base_site.html rename to app/templates/admin/base_site.html diff --git a/application/app/templates/admin/index.html b/app/templates/admin/index.html similarity index 100% rename from application/app/templates/admin/index.html rename to app/templates/admin/index.html diff --git a/application/app/templates/baselayout.html b/app/templates/baselayout.html similarity index 100% rename from application/app/templates/baselayout.html rename to app/templates/baselayout.html diff --git a/application/app/templates/deposit.html b/app/templates/deposit.html similarity index 100% rename from application/app/templates/deposit.html rename to app/templates/deposit.html diff --git a/application/app/templates/footer.html b/app/templates/footer.html similarity index 100% rename from application/app/templates/footer.html rename to app/templates/footer.html diff --git a/application/app/templates/globalmessage.html b/app/templates/globalmessage.html similarity index 100% rename from application/app/templates/globalmessage.html rename to app/templates/globalmessage.html diff --git a/application/app/templates/history.html b/app/templates/history.html similarity index 100% rename from application/app/templates/history.html rename to app/templates/history.html diff --git a/application/app/templates/index.html b/app/templates/index.html similarity index 100% rename from application/app/templates/index.html rename to app/templates/index.html diff --git a/application/app/templates/order.html b/app/templates/order.html similarity index 100% rename from application/app/templates/order.html rename to app/templates/order.html diff --git a/application/app/templates/registration/logged_out.html b/app/templates/registration/logged_out.html similarity index 100% rename from application/app/templates/registration/logged_out.html rename to app/templates/registration/logged_out.html diff --git a/application/app/templates/registration/login.html b/app/templates/registration/login.html similarity index 100% rename from application/app/templates/registration/login.html rename to app/templates/registration/login.html diff --git a/application/app/templates/statistics.html b/app/templates/statistics.html similarity index 100% rename from application/app/templates/statistics.html rename to app/templates/statistics.html diff --git a/application/app/templates/supply.html b/app/templates/supply.html similarity index 100% rename from application/app/templates/supply.html rename to app/templates/supply.html diff --git a/application/app/templates/userpanel.html b/app/templates/userpanel.html similarity index 100% rename from application/app/templates/userpanel.html rename to app/templates/userpanel.html diff --git a/application/app/urls.py b/app/urls.py similarity index 91% rename from application/app/urls.py rename to app/urls.py index 70feadd..f6f8cc4 100644 --- a/application/app/urls.py +++ b/app/urls.py @@ -16,10 +16,8 @@ urlpatterns = [ path('accounts/password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'), path('accounts/password_change_done/', views.redirect_home, name='password_change_done'), path('admin/', adminSite.urls), - # custom-handled resources - path('profilepictures', views.profile_pictures), # API # path('api/order-drink', views.api_order_drink), path('api/deposit', views.api_deposit), path('api/supply', views.api_supply) -] \ No newline at end of file +] diff --git a/application/app/views.py b/app/views.py similarity index 89% rename from application/app/views.py rename to app/views.py index 33e4b49..abb0023 100644 --- a/application/app/views.py +++ b/app/views.py @@ -15,7 +15,6 @@ from django.http.response import HttpResponse from django.shortcuts import render from django.utils.translation import gettext as _ - from django.utils.formats import decimal from . import sql_queries @@ -24,12 +23,6 @@ from .models import Drink from .models import Order from .models import RegisterTransaction -# - -profile_pictures_path = Path(settings.PROFILE_PICTURES).resolve() - -# login view - def login_page(request): @@ -67,8 +60,6 @@ def login_page(request): }) -# actual application - @login_required def index(request): context = { @@ -76,6 +67,7 @@ def index(request): } return render(request, "index.html", context) + @login_required def history(request): context = { @@ -83,6 +75,7 @@ def history(request): } return render(request, "history.html", context) + @login_required def order(request, drinkid): try: @@ -94,10 +87,12 @@ def order(request, drinkid): except Drink.DoesNotExist: return HttpResponseRedirect("/") + @login_required def deposit(request): return render(request, "deposit.html", {}) + @login_required def statistics(request): context = { @@ -110,57 +105,34 @@ def statistics(request): } return render(request, "statistics.html", context) + @login_required def supply(request): return render(request, "supply.html") + @login_required def redirect_home(request): return HttpResponseRedirect("/") -# Custom-Handled Resources - -def profile_pictures(request): - if not "name" in request.GET: - return HttpResponse(b"", status=400) - ppic_filepath = Path(profile_pictures_path / request.GET["name"]).resolve() - try: - ppic_filepath.relative_to(profile_pictures_path) - except: - return HttpResponse("No.", status=403) - if ppic_filepath.is_file(): - return FileResponse(ppic_filepath.open('rb')) - else: - return FileResponse(b"", status=404) - - # API for XHR requests # @login_required def api_order_drink(request): - # check request -> make order - user = request.user - try: - if user.allow_order_with_negative_balance or user.balance > 0: - drinkid = int(request.POST["drinkid"]) amount = int(request.POST["numberofdrinks"]) - drink = Drink.objects.get(pk=drinkid) - if ((drink.do_not_count and drink.available > 0) or (drink.available >= amount)) and not drink.deleted: Order.objects.create(drink=drink, user=user, amount=amount) return HttpResponse("success", status=200) else: return HttpResponse("notAvailable", status=400) - else: raise Exception("Unexpected input or missing privileges.") - except Exception as e: print(f"An exception occured while processing an order: User: {user.username} - Exception: {e}", file=sys.stderr) return HttpResponse(b"", status=500) @@ -168,15 +140,10 @@ def api_order_drink(request): @login_required def api_deposit(request): - # check request -> deposit - user = request.user - try: - amount = decimal.Decimal(request.POST["depositamount"]) - if 0.00 < amount < 9999.99: # create transaction RegisterTransaction.objects.create( @@ -185,26 +152,19 @@ def api_deposit(request): is_user_deposit=True, user=user ) - # return HttpResponse("success", status=200) else: raise Exception("Deposit amount too big or small.") - except Exception as e: print(f"An exception occured while processing a transaction: User: {user.username} - Exception: {e}", file=sys.stderr) return HttpResponse(b"", status=500) @login_required def api_supply(request): - # check request -> supply - user = request.user - try: - price = decimal.Decimal(request.POST["supplyprice"]) description = str(request.POST["supplydescription"]) - if 0.00 < price < 9999.99 and (user.allowed_to_supply or user.is_superuser): # create transaction RegisterTransaction.objects.create( @@ -213,10 +173,8 @@ def api_supply(request): is_user_deposit=False, user=user ) - # return HttpResponse("success", status=200) else: raise Exception("Unexpected input or missing privileges.") - except Exception as e: print(f"An exception occured while processing a supply transaction: User: {user.username} - Exception: {e}", file=sys.stderr) return HttpResponse(b"", status=500) diff --git a/application/app/apps.py b/application/app/apps.py deleted file mode 100644 index e61ab8c..0000000 --- a/application/app/apps.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.apps import AppConfig -from django.contrib.admin.apps import AdminConfig - - -class DAppConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'app' diff --git a/application/app/middleware.py b/application/app/middleware.py deleted file mode 100644 index 43acf6c..0000000 --- a/application/app/middleware.py +++ /dev/null @@ -1,11 +0,0 @@ - -# Define CSP middleware: - -def csp_middleware(get_response): - - def middleware(request): - response = get_response(request) - response["content-security-policy"] = "default-src 'self'" - return response - - return middleware diff --git a/application/app/tests.py b/application/app/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/application/app/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/application/drinks_manager/settings.py b/application/drinks_manager/settings.py deleted file mode 100644 index d01503f..0000000 --- a/application/drinks_manager/settings.py +++ /dev/null @@ -1,179 +0,0 @@ -""" -Django settings for drinks_manager project. - -Generated by 'django-admin startproject' using Django 3.2.5. - -For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ -""" - -import os - -from pathlib import Path - - -# Build paths inside the project like this: BASE_DIR / 'subdir'. -BASE_DIR = Path(__file__).resolve().parent.parent - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key secret! -django_secret_key_absolute_fp = os.environ["DJANGO_SK_ABS_FP"] -with open(django_secret_key_absolute_fp) as secret_key_file: - SECRET_KEY = secret_key_file.read().strip() - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = (os.environ["DJANGO_DEBUG"].lower() == "true") - - -ALLOWED_HOSTS = [ - "*" -] - - -### ----------------- ### - - -# Application definition - -INSTALLED_APPS = [ - "app.apps.DAppConfig", - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', -] - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - "django.middleware.locale.LocaleMiddleware", - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - "django_currentuser.middleware.ThreadLocalUserMiddleware", - "app.middleware.csp_middleware" -] - -ROOT_URLCONF = 'drinks_manager.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - "app.context_processors.app_version" - ], - }, - }, -] - -WSGI_APPLICATION = 'drinks_manager.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/3.2/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': os.environ["PGDB_DB"], - 'USER': os.environ["PGDB_USER"], - 'PASSWORD': os.environ["PGDB_PASSWORD"], - 'HOST': os.environ["PGDB_HOST"], - 'PORT': str(os.environ["PGDB_PORT"]) - } -} - -CONN_MAX_AGE = 20 # keep database connections alive for n seconds - - -# Password validation -# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators - -if os.environ["DJANGO_ENABLE_PASSWORD_VALIDATION"].lower() == "true": - AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, - ] -else: - AUTH_PASSWORD_VALIDATORS = [] - - -AUTH_USER_MODEL = "app.User" - -# user will be logged out after x seconds -SESSION_COOKIE_AGE = int(os.environ["DJANGO_SESSION_COOKIE_AGE"]) - - -# more security settings - -CSRF_COOKIE_SECURE = True -SESSION_COOKIE_SECURE = True - - -# Internationalization -# https://docs.djangoproject.com/en/3.2/topics/i18n/ - -LANGUAGE_CODE = os.environ["DJANGO_LANGUAGE_CODE"] # this is the default and fallback language (currently only de-de and en-us supported) - -TIME_ZONE = os.environ["DJANGO_TIME_ZONE"] - -USE_I18N = True - -USE_L10N = True - -USE_TZ = True - -LOCALE_PATHS = [ - BASE_DIR / "locale" -] - - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/3.2/howto/static-files/ - -STATIC_URL = '/static/' -STATIC_ROOT = os.environ["STATIC_FILES"] - - -# Default primary key field type -# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' - -# - -APP_VERSION = os.environ["APP_VERSION"] - -try: - CURRENCY_SUFFIX = os.environ["CURRENCY_SUFFIX"] -except KeyError: - CURRENCY_SUFFIX = "$" - -PROFILE_PICTURES = os.environ["PROFILE_PICTURES"] diff --git a/config/config.sample.sh b/config/config.sample.sh deleted file mode 100644 index 51aa8f0..0000000 --- a/config/config.sample.sh +++ /dev/null @@ -1,31 +0,0 @@ -# environment variables - -export HTTP_PORT=80 # required by caddy, will be redirected to https -export HTTPS_PORT=443 # actual port for the webinterface - -export DJANGO_PORT=8001 # caddy's http port (should be blocked by the firewall) - -export DJANGO_SESSION_COOKIE_AGE=600 # auto-logout, in seconds -export SESSION_CLEAR_INTERVAL=120 # interval for automatic session clearing, in minutes - -export DJANGO_LANGUAGE_CODE="en" # the default and fallback language, currently only de and en are supported. -export DJANGO_TIME_ZONE="CET" # your timezone - -export CURRENCY_SUFFIX="$" # if you have another currency symbol, you can specify it here - -# Do you want to enable password validation? -# (numeric PINs as Password will not be seen as valid) -export DJANGO_ENABLE_PASSWORD_VALIDATION="true" - -# database connection (postgresql) -export PGDB_DB="" # The name of the database -export PGDB_USER="" # The database user -export PGDB_PASSWORD='' # The password for the database user -export PGDB_HOST="127.0.0.1" # The hostname of your database -export PGDB_PORT=5432 # The port your database is listening on - -# log files -# only change if you know what you are doing -export CADDY_ACCESS_LOG="$(pwd)/logs/http-access.log" -export CADDY_LOG="$(pwd)/logs/caddy.log" -export APPLICATION_LOG="$(pwd)/logs/application.log" diff --git a/config/Caddyfile b/data/Caddyfile similarity index 56% rename from config/Caddyfile rename to data/Caddyfile index e5fe817..94b7a54 100644 --- a/config/Caddyfile +++ b/data/Caddyfile @@ -1,29 +1,36 @@ { - # disable admin backend + # disable unwanted stuff admin off + skip_install_trust # define the ports by the environment variables http_port {$HTTP_PORT} https_port {$HTTPS_PORT} } -https:// { +0.0.0.0 { # the tls certificates - tls ./config/tls/server.pem ./config/tls/server-key.pem + tls {$DATADIR}/tls/server.pem {$DATADIR}/tls/server-key.pem route { + # profile pictures + file_server /profilepictures/* { + root {$DATADIR}/profilepictures/.. + } # static files file_server /static/* { - root {$STATIC_FILES}/.. + root {$DATADIR}/static/.. } # favicon redir /favicon.ico /static/favicon.ico # reverse proxy to the (django) application - reverse_proxy localhost:{$DJANGO_PORT} + reverse_proxy localhost:{$APPLICATION_PORT} + # set additional security headers + header Content-Security-Policy "default-src 'self'" } # use compression encode gzip # logging log { - output file {$CADDY_ACCESS_LOG} + output file {$ACCESS_LOG} format filter { wrap console fields { diff --git a/data/config.example.yml b/data/config.example.yml new file mode 100644 index 0000000..c24a2c8 --- /dev/null +++ b/data/config.example.yml @@ -0,0 +1,37 @@ +--- +app: + # The secret key, used for security protections + # This MUST be a secret, very long, random string + secret_key: "!!!insert random data!!!" + # The port for the asgi application + # This should be blocked by the firewall + application_port: 8001 + # Used for auto-logout, in seconds + session_cookie_age: 600 + # Interval for automatic session clearing, in minutes + session_clear_interval: 120 + # The default and fallback language, currently only de and en are supported. + language_code: "en" + # Your timezone + timezone: "CET" + # Specify the suffix for your currency + currency_suffix: "$" + # Enable/Disable password validation + # (numeric PINs are NOT valid when this is set to true) + password_validation: true +db: + # Database configuration + database: "drinks" + user: "drinks" + password: "insert password" + host: "127.0.0.1" + port: 5432 +caddy: + # Ports that the web server listens on + http_port: 80 + https_port: 443 +logs: + # Logfile paths + caddy: "./data/logs/caddy.log" + http_access: "./data/logs/http-access.log" + application: "./data/logs/application.log" diff --git a/archive/.gitkeep b/data/logs/.gitkeep similarity index 100% rename from archive/.gitkeep rename to data/logs/.gitkeep diff --git a/config/tls/.gitkeep b/data/tls/.gitkeep similarity index 100% rename from config/tls/.gitkeep rename to data/tls/.gitkeep diff --git a/docs/Commands.md b/docs/Commands.md deleted file mode 100644 index b47bbc3..0000000 --- a/docs/Commands.md +++ /dev/null @@ -1,81 +0,0 @@ -# Commands - -You run a command with - -``` -./run.sh -``` - -## Available Commands - ---- - -### `server` -This starts the application (a caddy instance, uvicorn with the Django application and a scheduler that automatically removes expired session data). -Log files will be written. - ---- - -### `setup` -This sets up some database tables, views, and more, generates a secret key for the application and lets you create an admin user. - ---- - -### `create-admin` -Lets you create an admin user - ---- - -### `generate-secret-key` -Generate a new random secret key for Django. -This will overwrite the old one. -Warning: After running this, current sessions will be invalid, and the users have to relogin. Don't run this command while the server is running. - ---- - -### `clear-sessions` -manually remove all expired sessions from the database - ---- - -### `force-db-upgrade` -force a database migration and -upgrade. -This is mainly used in development. - ---- - -### `archive-tables` -archive (copy & delete) all entries in app_order and app_registertransaction. -Use this to archive old orders or transactions (e.g. when the database gets too big). - ---- - -### `development-server` -This starts a caddy instance, the Django development server with DEBUGGING enabled and the session-clear-scheduler. -Only the HTTP-Access-Log will be written to its logfile, other logs will be written to the console. - ---- - -### `shell` - -Start a Django shell. - ---- - -### `help` -Show a help text - ---- - - -## Examples - -Run the production server: -``` -./run.sh server -``` - -Create a new admin: -``` -./run.sh create-admin -``` \ No newline at end of file diff --git a/docs/Configuration.md b/docs/Configuration.md deleted file mode 100644 index 00d5933..0000000 --- a/docs/Configuration.md +++ /dev/null @@ -1,14 +0,0 @@ -# Configuration - -## Main Configuration - -`config/config.sh` - -There is a sample configuration with explanations: [/config/config.sample.sh](/config/config.sample.sh) - - -## Caddy (Reverse Proxy & Static File Server) - -[config/Caddyfile](/config/Caddyfile) - -The default configuration should work out of the box, don't edit this file unless you know what you're doing. diff --git a/docs/Setup.md b/docs/Setup.md deleted file mode 100644 index bf3d0c4..0000000 --- a/docs/Setup.md +++ /dev/null @@ -1,110 +0,0 @@ -# Setup - -## I. Dependencies - -Before the actual setup, you have to satisfy the following dependencies: - - -### System - -- `pg_config` - - Ubuntu: `libpq-dev` - - Fedora/RHEL: `libpq-devel` -- `Caddy` 2.4.3+ (HTTP Reverse Proxy & Static File Server) -- `gcc`, `gettext` -- `Python` 3.9+ with pip - - `Python` header files - - Fedora/RHEL: `python3-devel` - - Ubuntu: `python3-dev` - - -### Python Packages (pip) - -All required python packages are listed in [requirements.txt](/requirements.txt) - -You can install the required python packages with -```bash -./install-pip-dependencies.sh -``` - -## II.A Installation - -You can get the latest version with git: - -``` -git clone --branch release-x https://gitlab.com/W13R/drinks-manager.git -``` -(replace x with the latest version) - -Alternatively, you can download the [latest release](https://gitlab.com/W13R/drinks-manager/-/releases) and extract the files to your prefered destination. - -**Warning:** - -Make shure that you set the correct file permissions, especially for the config files !! - -The following should be sufficient: - -```bash -chmod -R u+rw,g+r,g-w,o-rwx -``` - - -## II.B Update - -If you installed the application with git, you can run the following in the drinks-manager directory to update to the new version: - -``` -git fetch -git checkout x -``` -(replace x with the new version) - -If you downloaded the application from the releases page, you can download the new release in the same manner, and overwrite the old files with the new ones. - -You have to restart the application server to apply the changes. -WARNING: The auto-upgrade mechanism may expect you to input information. Therefore, you should start the application from the command-line the first time after an update. - -Further upgrading-instructions may be provided in the Release Notes on the Releases Page of this Project (Deployments -> Releases). - - -## III. Database - -This project is using PostgreSQL. You have to set up a database: - -```sql -create user drinksmanager password ''; -create database drinksmgr owner drinksmanager; -``` - -After creating the user, you have to edit your `pg_hba.conf` (see https://www.postgresql.org/docs/current/auth-pg-hba-conf.html). -Add the following line: -``` -host drinksmgr drinksmanager 127.0.0.1/32 md5 -``` - -Now you can configure your database connection in `config/config.sh`. - - -## IV. HTTPS & TLS Certificates - -A TLS/SSL certificate and key is required. -Filepaths: - -- `config/tls/server.pem` for the certificate -- `config/tls/server-key.pem` for the key - -You can set another filepath for those files in your caddy configuration at [config/Caddyfile](/config/Caddyfile). - - -## V. Configuration - -see [Configuration](Configuration.md) - - -## VI. Run Setup Command - -run `./run.sh setup` - -This will automatically set up database tables, views and entries, set up Django and let you create a admin user. - -After this, start the server with `./run.sh server` and navigate to `https://your.ip.add.ress:port/admin/`. diff --git a/install-pip-dependencies.sh b/install-pip-dependencies.sh deleted file mode 100755 index 6c02848..0000000 --- a/install-pip-dependencies.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -# install the required python packages - -wd=$(dirname $0) - -pip3 install -r "$wd/requirements.txt" -t "$wd/packages" diff --git a/lib/activate-devel-env.sh b/lib/activate-devel-env.sh deleted file mode 100755 index 3467721..0000000 --- a/lib/activate-devel-env.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -source ./lib/env.sh -source ./config/config.sh -export DJANGO_DEBUG=true -export PYTHONPATH="./packages" diff --git a/lib/archive-tables.py b/lib/archive-tables.py deleted file mode 100644 index a1901cc..0000000 --- a/lib/archive-tables.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python3 - -import os, sys - -from datetime import datetime -from pathlib import Path - -from psycopg2 import connect - - -# archive (copy & delete) all entries in app_order and app_registertransaction - -timestamp = datetime.now().strftime("%Y-%m-%d-%H%M%S") -archive_folder = Path("./archive") -orders_archive_path = archive_folder / ("orders-archive-" + timestamp + ".csv") -transactions_archive_path = archive_folder / ("transactions-archive-" + timestamp + ".csv") - - -if __name__ == "__main__": - exit_code = 1 - connection = connect( - user = os.environ["PGDB_USER"], - password = os.environ["PGDB_PASSWORD"], - host = os.environ["PGDB_HOST"], - port = os.environ["PGDB_PORT"], - database = os.environ["PGDB_DB"] - ) - cur = connection.cursor() - try: - print(f"Starting archiving to {orders_archive_path.__str__()} and {transactions_archive_path.__str__()}...") - # # # # # - # copy - with orders_archive_path.open("w") as of: - cur.copy_expert( - "copy (select * from app_order) to STDOUT with csv delimiter ';'", - of - ) - with transactions_archive_path.open("w") as tf: - cur.copy_expert( - "copy (select * from app_registertransaction) to STDOUT with csv delimiter ';'", - tf - ) - # delete - cur.execute("delete from app_order;") - cur.execute("delete from app_registertransaction;") - connection.commit() - # # # # # - exit_code = 0 - print("done.") - except (Error, Exception) as err: - connection.rollback() - print(f"An error occured while upgrading the database at {os.environ['PGDB_HOST']}:\n{err}") - exit_code = 1 - finally: - cur.close() - connection.close() - exit(exit_code) diff --git a/lib/auto-upgrade-db.sh b/lib/auto-upgrade-db.sh deleted file mode 100644 index beadb59..0000000 --- a/lib/auto-upgrade-db.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - - -echo -e "Checking if database needs an upgrade..." - -if python3 $(pwd)/lib/verify-db-app-version.py; then - - echo -e "No database upgrade needed." - -else - - echo -e "Starting automatic database upgrade..." - source "$(pwd)/lib/db-migrations.sh" - python3 $(pwd)/lib/upgrade-db.py - -fi diff --git a/lib/bootstrap.py b/lib/bootstrap.py deleted file mode 100644 index 23f0d34..0000000 --- a/lib/bootstrap.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 - - -from os import environ -from os import getcwd -from shlex import quote -from signal import SIGINT -from subprocess import run -from subprocess import Popen -from sys import argv -from sys import stdout -from sys import stderr - - -# some vars -devel = False -caddy_process = None -scs_process = None -app_process = None - - -def stop(): - print("\n\nStopping services.\n\n") - caddy_process.send_signal(SIGINT) - scs_process.send_signal(SIGINT) - app_process.send_signal(SIGINT) - print(f"Caddy stopped with exit code {caddy_process.wait()}.") - print(f"session-clear-scheduler stopped with exit code {scs_process.wait()}.") - if devel: - print(f"Django stopped with exit code {app_process.wait()}.") - else: - print(f"Django/Uvicorn stopped with exit code {app_process.wait()}.") - if caddy_process.returncode != 0 or scs_process.returncode != 0 or app_process.returncode !=0: - exit(1) - else: - exit(0) - - -if __name__ == "__main__": - # development or production environment? - try: - if argv[1] == "devel": - devel = True - except IndexError: - pass - # vars - pwd = getcwd() - APPLICATION_LOG = environ["APPLICATION_LOG"] - CADDY_ACCESS_LOG = environ["CADDY_ACCESS_LOG"] - CADDY_LOG = environ["CADDY_LOG"] - DJANGO_PORT = environ["DJANGO_PORT"] - HTTPS_PORT = environ["HTTPS_PORT"] - if devel: - environ["DJANGO_DEBUG"] = "true" - else: - environ["DJANGO_DEBUG"] = "false" - # info - print(f"\n\nStarting server on port {HTTPS_PORT}...\nYou should be able to access the application locally at https://127.0.0.1:{HTTPS_PORT}/\n\nPress Ctrl+C to stop all services.\n\n") - if not devel: - print(f"All further messages will be written to {APPLICATION_LOG} and {CADDY_LOG}") - print(f"HTTP Access Log will be written to {CADDY_ACCESS_LOG}") - try: - # start django/uvicorn - if devel: - run( - ["python3", f"{pwd}/application/manage.py", "collectstatic", "--noinput"], - stdout=stdout, - stderr=stderr, - env=environ - ) - app_process = Popen( - ["python3", f"{pwd}/application/manage.py", "runserver", f"127.0.0.1:{DJANGO_PORT}"], - stdout=stdout, - stderr=stderr, - env=environ - ) - else: - application_log_file = open(APPLICATION_LOG, "a") - run( - ["python3", f"{pwd}/application/manage.py", "collectstatic", "--noinput"], - stdout=application_log_file, - stderr=application_log_file, - env=environ - ) - app_process = Popen( - [ - "python3", "-m", "uvicorn", - "--host", "127.0.0.1", - "--port", quote(DJANGO_PORT), - "drinks_manager.asgi:application" - ], - stdout=application_log_file, - stderr=application_log_file, - cwd=f"{pwd}/application/", - env=environ - ) - # start caddy - if devel: - caddy_log_file = stdout - caddy_log_file_stderr = stderr - else: - caddy_log_file = caddy_log_file_stderr = open(CADDY_LOG, "a") - caddy_process = Popen( - ["caddy", "run", "--config", f"{pwd}/config/Caddyfile"], - stdout=caddy_log_file, - stderr=caddy_log_file_stderr, - env=environ - ) - # start session-clear-scheduler - if devel: - clear_sched_log_file = stdout - clear_sched_log_file_stderr = stderr - else: - clear_sched_log_file = clear_sched_log_file_stderr = open(APPLICATION_LOG, "a") - scs_process = Popen( - ["python3", f"{pwd}/lib/session-clear-scheduler.py"], - stdout=clear_sched_log_file, - stderr=clear_sched_log_file_stderr - ) - caddy_process.wait() - scs_process.wait() - app_process.wait() - except KeyboardInterrupt: - stop() diff --git a/lib/clear-expired-sessions.sh b/lib/clear-expired-sessions.sh deleted file mode 100644 index c10b5ce..0000000 --- a/lib/clear-expired-sessions.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -# enable debugging for this command -export DJANGO_DEBUG="true" - -# make migrations & migrate -python3 $(pwd)/application/manage.py clearsessions \ No newline at end of file diff --git a/lib/create-admin.sh b/lib/create-admin.sh deleted file mode 100644 index ee46fd4..0000000 --- a/lib/create-admin.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - - -# enable debugging for this command -export DJANGO_DEBUG="true" - -# make migrations & migrate -python3 $(pwd)/application/manage.py createsuperuser - -echo -e "done." \ No newline at end of file diff --git a/lib/db-migrations.sh b/lib/db-migrations.sh deleted file mode 100644 index 7c17843..0000000 --- a/lib/db-migrations.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - - -# enable debugging for this command -export DJANGO_DEBUG="true" - -# make migrations & migrate -python3 $(pwd)/application/manage.py makemigrations -python3 $(pwd)/application/manage.py makemigrations app -python3 $(pwd)/application/manage.py migrate - -echo -e "done with db migration." \ No newline at end of file diff --git a/lib/env.sh b/lib/env.sh deleted file mode 100644 index 5863525..0000000 --- a/lib/env.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -export DJANGO_SK_ABS_FP="$(pwd)/config/secret_key.txt" -export PROFILE_PICTURES="$(pwd)/profilepictures/" -export STATIC_FILES="$(pwd)/static/" -export APP_VERSION="13" -export PYTHONPATH="$(pwd)/packages/" diff --git a/lib/generate-secret-key.py b/lib/generate-secret-key.py deleted file mode 100644 index 7f98866..0000000 --- a/lib/generate-secret-key.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -from pathlib import Path -from secrets import token_bytes -from base64 import b85encode - -# - -override = False -if len(sys.argv) > 1: - if sys.argv[1] == "--override": - override = True - -random_token_length = 128 - -secret_key_fp = Path("config/secret_key.txt") - -# - -if secret_key_fp.exists() and not override: - print(f"Warning: secret_key.txt already exists in directory {secret_key_fp.absolute()}. Won't override.", file=sys.stderr) - exit(1) -else: - print("Generating random secret key...") - random_key = b85encode(token_bytes(random_token_length)) - with secret_key_fp.open("wb") as secret_key_f: - secret_key_f.write(random_key) - print("done.") \ No newline at end of file diff --git a/lib/session-clear-scheduler.py b/lib/session-clear-scheduler.py deleted file mode 100644 index 6096d72..0000000 --- a/lib/session-clear-scheduler.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 - -# This script clears expired sessions in a regular interval -# The interval is defined (in minutes) by config.sh (SESSION_CLEAR_INTERVAL) - -import os - -from pathlib import Path -from subprocess import run -from time import sleep -from datetime import datetime - -try: - - exiting = False - clear_running = False - - print("[session-clear-scheduler] Starting session-clear-scheduler.") - - session_clear_script_fp = Path("lib/clear-expired-sessions.sh") - clear_interval_seconds = int(os.environ["SESSION_CLEAR_INTERVAL"]) * 60 - - sleep(10) # wait some seconds before the first session clean-up - - while True: - - clear_running = True - run(["/bin/sh", session_clear_script_fp.absolute()]) - clear_running = False - - print(f"[session-clear-scheduler: {datetime.now()}] Cleared expired sessions.") - - if exiting: - break - - sleep(clear_interval_seconds) - -except KeyboardInterrupt: - - exiting = True - - if clear_running: - print(f"[session-clear-scheduler: {datetime.now()}] Received SIGINT. Waiting for current clear process to finish.") - sleep(20) # wait some time - - print(f"[session-clear-scheduler: {datetime.now()}] Exiting") - exit(0) diff --git a/lib/setup-application.sh b/lib/setup-application.sh deleted file mode 100644 index 56ae66d..0000000 --- a/lib/setup-application.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - - -# enable debugging for this command -export DJANGO_DEBUG="true" - -python3 "$(pwd)/lib/generate-secret-key.py" - -source "$(pwd)/lib/db-migrations.sh" - -python3 $(pwd)/lib/upgrade-db.py - -echo -e "\nCreate admin account. Email is optional.\n" -source "$(pwd)/lib/create-admin.sh" - -python3 $(pwd)/application/manage.py collectstatic --noinput diff --git a/lib/start-django-shell.sh b/lib/start-django-shell.sh deleted file mode 100644 index a696310..0000000 --- a/lib/start-django-shell.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -# start a django shell - -export DJANGO_DEBUG="true" - -oldcwd="$(pwd)" -echo "Starting a django shell..." -echo -e "--------------------------------------------------------------------------------\n" -"$(pwd)/application/manage.py" shell -echo -e "\n--------------------------------------------------------------------------------" -cd "$oldcwd" \ No newline at end of file diff --git a/lib/upgrade-db.py b/lib/upgrade-db.py deleted file mode 100644 index d07da87..0000000 --- a/lib/upgrade-db.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 - -import os, sys - -from pathlib import Path - -from psycopg2 import connect -from psycopg2._psycopg import cursor as _cursor -from psycopg2._psycopg import connection as _connection -from psycopg2 import Error -from psycopg2 import IntegrityError -from psycopg2 import errorcodes - - -# setup or upgrade the database - -def log(s, error=False): - if error: - print(f"{s}", file=sys.stderr) - else: - print(f"{s}", file=sys.stdout) - - -def execute_sql_statement(cursor:_cursor, connection:_connection, sql_statement): - try: - cursor.execute(sql_statement) - connection.commit() - except IntegrityError as ie: - if ie.pgcode == errorcodes.UNIQUE_VIOLATION: - log("Skipping one row that already exists.") - connection.rollback() - else: - log(f"An integrity error occured:\n{ie}\nRolling back...", error=True) - connection.rollback() - except Error as e: - log(f"An SQL statement failed while upgrading the database at {os.environ['PGDB_HOST']}:\n{e}", error=True) - connection.rollback() - - -if __name__ == "__main__": - exit_code = 1 - conn = connect( - user = os.environ["PGDB_USER"], - password = os.environ["PGDB_PASSWORD"], - host = os.environ["PGDB_HOST"], - port = os.environ["PGDB_PORT"], - database = os.environ["PGDB_DB"] - ) - cur = conn.cursor() - try: - log("\nSetting up/upgrading database...") - # # # # # - log("Not deleting register_balance. You can delete it via the Admin Panel (Globals -> register_balance), as it is no more used.") - execute_sql_statement(cur, conn, """ - insert into app_global - values ('global_message', 'Here you can set a global message that will be shown to every user.', 0.0, ''); - """) - execute_sql_statement(cur, conn, """ - insert into app_global - values ('admin_info', 'Here you can set am infotext that will be displayed on the admin panel.', 0.0, ''); - """) - execute_sql_statement(cur, conn, """ - create or replace view app_userdeposits_view as - select * from app_registertransaction - where is_user_deposit = true; - """) - # # # # # - # set app_version in file and database - # database - try: - cur.execute(""" - select value from application_info - where key = 'app_version'; - """) - result = cur.fetchone() - if result == None: - cur.execute(f""" - insert into application_info values ('app_version', '{os.environ['APP_VERSION']}'); - """) - conn.commit() - else: - cur.execute(f""" - update application_info set value = '{os.environ['APP_VERSION']}' where key = 'app_version'; - """) - conn.commit() - except Error as err: - if err.pgcode == errorcodes.UNDEFINED_TABLE: - try: - conn.rollback() - cur.execute(""" - create table application_info ( - key varchar(32) primary key, - value text - ); - """) - cur.execute(f""" - insert into application_info values ('app_version', '{os.environ['APP_VERSION']}'); - """) - conn.commit() - except Error as err2: - log(f"An error occurred while setting app_version in table application_info: {err}", error=True) - exit_code = 1 - else: - log(f"An error occurred while setting app_version in table application_info: {err}", error=True) - exit_code = 1 - # file - Path("./config/db_app_version.txt").write_text(os.environ["APP_VERSION"]) - # done - exit_code = 0 - log("done with db setup/upgrade.") - except (Error, Exception) as err: - log(f"An error occured while upgrading the database at {os.environ['PGDB_HOST']}:\n{err}", error=True) - exit_code = 1 - finally: - cur.close() - conn.close() - exit(exit_code) diff --git a/lib/verify-db-app-version.py b/lib/verify-db-app-version.py deleted file mode 100644 index 3fb10f9..0000000 --- a/lib/verify-db-app-version.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 - -from os import environ -from pathlib import Path - -from psycopg2 import connect -from psycopg2._psycopg import cursor -from psycopg2 import Error -from psycopg2 import errorcodes - - -# verify if the installation -# exit code 0 -> no database update is necessary -# exit code 1 -> database update is necessary - - -def check_file(): - db_app_version_file = Path("./config/db_app_version.txt") - if not db_app_version_file.exists(): - exit(1) - if not db_app_version_file.is_file(): - exit(1) - if not db_app_version_file.read_text().strip(" ").strip("\n") == environ["APP_VERSION"]: - exit(1) - - -def check_database(): - connection = connect( - user = environ["PGDB_USER"], - password = environ["PGDB_PASSWORD"], - host = environ["PGDB_HOST"], - port = environ["PGDB_PORT"], - database = environ["PGDB_DB"] - ) - cur = connection.cursor() - try: - # check application version in db - cur.execute(""" - select value from application_info - where key = 'app_version'; - """) - appinfo_result = list(cur.fetchone())[0] - if appinfo_result == None: - cur.close() - connection.close() - exit(1) - if appinfo_result != environ["APP_VERSION"]: - cur.close() - connection.close() - exit(1) - # check rows in app_global - required_rows = [ - "global_message", - "admin_info" - ] - cur.execute(""" - select name from app_global; - """) - table_global_result = list(cur.fetchall()) - cur.close() - connection.close() - existing_rows = [list(row)[0] for row in table_global_result] - for r in required_rows: - if not r in existing_rows: - exit(1) - except Error: - cur.close() - connection.close() - exit(1) - except Exception as e: - print(f"An exception occured: {e}") - cur.close() - connection.close() - exit(1) - - -if __name__ == "__main__": - check_file() - check_database() - exit(0) diff --git a/application/locale/de/LC_MESSAGES/django.mo b/locales/de/LC_MESSAGES/django.mo similarity index 100% rename from application/locale/de/LC_MESSAGES/django.mo rename to locales/de/LC_MESSAGES/django.mo diff --git a/application/locale/de/LC_MESSAGES/django.po b/locales/de/LC_MESSAGES/django.po similarity index 100% rename from application/locale/de/LC_MESSAGES/django.po rename to locales/de/LC_MESSAGES/django.po diff --git a/application/manage.py b/manage.py similarity index 80% rename from application/manage.py rename to manage.py index dce56eb..e170f6b 100755 --- a/application/manage.py +++ b/manage.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python """Django's command-line utility for administrative tasks.""" import os import sys @@ -6,7 +6,7 @@ import sys def main(): """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drinks_manager.settings') + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: @@ -18,5 +18,5 @@ def main(): execute_from_command_line(sys.argv) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/misc/drinks-manager.service b/misc/drinks-manager.service deleted file mode 100644 index 9dbc463..0000000 --- a/misc/drinks-manager.service +++ /dev/null @@ -1,25 +0,0 @@ -# This is a sample service file for drinks manager - -[Unit] -After=network.target network-online.target -Requires=network-online.target -Description=Drinks Manager - -[Service] -User=drinks-manager -Group=drinks-manager -WorkingDirectory=/srv/drinks-manager/ -# start the server: -ExecStart=/usr/bin/bash -c "/srv/drinks-manager/run.sh server" -# stop the process with a SIGINT: -ExecStop=/usr/bin/bash -c "/bin/kill -2 $MAINPID; /usr/bin/sleep 10" -Restart=on-failure -TimeoutStopSec=40s -LimitNPROC=512 -LimitNOFILE=1048576 -AmbientCapabilities=CAP_NET_BIND_SERVICE -PrivateTmp=true -ProtectSystem=full - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/misc/icons/drinksmanager-icon-1024.png b/misc/icons/drinksmanager-icon-1024.png deleted file mode 100644 index 81233aa6f526f3205135706481fe958a4d86b273..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102831 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%0Ah3dS$Z36}&}ayNQXu=W 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 M+ke?s;Y?2bKWkY_%K!iX diff --git a/misc/icons/drinksmanager-icon.src.svg b/misc/icons/drinksmanager-icon.src.svg deleted file mode 100644 index f231677..0000000 --- a/misc/icons/drinksmanager-icon.src.svg +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Julian Müller (W13R) - - - - - - diff --git a/packages/.gitkeep b/packages/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/profilepictures/default.svg b/profilepictures/default.svg deleted file mode 100644 index 7138ef3..0000000 --- a/profilepictures/default.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - diff --git a/logs/.gitkeep b/project/__init__.py similarity index 100% rename from logs/.gitkeep rename to project/__init__.py diff --git a/application/drinks_manager/asgi.py b/project/asgi.py similarity index 56% rename from application/drinks_manager/asgi.py rename to project/asgi.py index dcfe5ee..486c89b 100644 --- a/application/drinks_manager/asgi.py +++ b/project/asgi.py @@ -1,16 +1,16 @@ """ -ASGI config for drinks_manager project. +ASGI config for project project. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ """ import os from django.core.asgi import get_asgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drinks_manager.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") application = get_asgi_application() diff --git a/project/settings.py b/project/settings.py new file mode 100644 index 0000000..cd594ec --- /dev/null +++ b/project/settings.py @@ -0,0 +1,160 @@ +""" +Django settings for project project. + +Generated by 'django-admin startproject' using Django 4.1.6. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" + +import os +from pathlib import Path +from yaml import safe_load + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + +# Load configuration file +with Path(BASE_DIR / "data" / "config.yml").open("r") as f: + config = safe_load(f) + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = config["app"]["secret_key"] +if SECRET_KEY == "!!!replace this with random data!!!" or len(SECRET_KEY) < 40: + print( + "WARNING: You didn't provide a secure secret_key in the configuration file!", + "This is a security risk!!!") + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True +if "APP_PROD" in os.environ: + DEBUG = not os.environ["APP_PROD"] + +# ALLOWED_HOSTS can be wildcarded, +# because caddy already handles requests +ALLOWED_HOSTS = ["*"] + +# Application definition + +INSTALLED_APPS = [ + "app.apps.AppConfig", + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.locale.LocaleMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +ROOT_URLCONF = "project.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "app.context_processors.app_version" + ], + }, + }, +] + +WSGI_APPLICATION = "project.wsgi.application" + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + +DATABASES = { + "default": { + "ENGINE": 'django.db.backends.postgresql', + "NAME": config["db"]["database"], + "USER": config["db"]["user"], + "PASSWORD": config["db"]["password"], + "HOST": config["db"]["host"], + "PORT": str(config["db"]["port"]), + } +} + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +if config["app"]["password_validation"]: + AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, + ] +else: + AUTH_PASSWORD_VALIDATORS = [] + +# Security settings + +AUTH_USER_MODEL = "app.User" +SESSION_COOKIE_AGE = int(config["app"]["session_cookie_age"]) +CSRF_COOKIE_SECURE = True +SESSION_COOKIE_SECURE = True + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = config["app"]["language_code"] +TIME_ZONE = config["app"]["timezone"] +USE_I18N = True +USE_L10N = True +USE_TZ = True + +LOCALE_PATHS = [ + BASE_DIR / "locales" +] + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = "static/" +STATIC_ROOT = BASE_DIR / "data" / "static" + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + +# Additional settings + +if "APP_VERSION" in os.environ: + APP_VERSION = os.environ["APP_VERSION"] +else: + APP_VERSION = "unknown" + +CURRENCY_SUFFIX = config["app"]["currency_suffix"] diff --git a/application/drinks_manager/urls.py b/project/urls.py similarity index 86% rename from application/drinks_manager/urls.py rename to project/urls.py index 5bf5958..77d62fb 100644 --- a/application/drinks_manager/urls.py +++ b/project/urls.py @@ -1,7 +1,7 @@ -"""drinks_manager URL Configuration +"""project URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/3.2/topics/http/urls/ + https://docs.djangoproject.com/en/4.1/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views @@ -13,9 +13,8 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ - from django.urls import path, include urlpatterns = [ path('', include("app.urls")) -] \ No newline at end of file +] diff --git a/application/drinks_manager/wsgi.py b/project/wsgi.py similarity index 56% rename from application/drinks_manager/wsgi.py rename to project/wsgi.py index b42c9aa..b5da491 100644 --- a/application/drinks_manager/wsgi.py +++ b/project/wsgi.py @@ -1,16 +1,16 @@ """ -WSGI config for drinks_manager project. +WSGI config for project project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drinks_manager.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") application = get_wsgi_application() diff --git a/requirements.txt b/requirements.txt index da50c9d..2be275b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django~=3.2.7 -django-currentuser==0.5.3 -psycopg2~=2.9.1 -uvicorn~=0.17.6 +Django~=4.1 +psycopg2~=2.9.5 +uvicorn~=0.20.0 +PyYAML~=6.0 diff --git a/run.sh b/run.sh deleted file mode 100755 index a1664c5..0000000 --- a/run.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env bash - - -function show_dm_help { # $1 = exit code - - echo -e "Usage:\t./run.sh \n" - echo -e "\nCommands:\n" - echo -e " server\t\tstart server" - echo -e " setup\t\t\tset up the application" - echo -e " create-admin\t\tcreate an admin account" - echo -e " generate-secret-key\tgenerate a new random secret key for Django" - echo -e " clear-sessions\tmanually remove all expired sessions from the database" - echo -e " force-db-upgrade\tforce a database migration & upgrade" - echo -e " archive-tables\tarchive (copy & delete) all entries in app_order and app_registertransaction" - echo -e " development-server\tstart Django development server and enable debugging" - echo -e " shell\t\t\tstart a Django shell" - echo -e " help\t\t\tShow this help text\n" - echo -e "\nExamples:\n" - echo -e " ./run.sh server" - echo -e " ./run.sh create-admin" - echo "" - - exit $1 - -} - -# set current working directory -cd $(dirname "$0") - -source "$(pwd)/lib/env.sh" - -echo -e "\n## Drinks Manager" -echo -e "## version $APP_VERSION\n" - - -if [ -z $1 ]; then - - show_dm_help 1 - -else - - source "$(pwd)/config/config.sh" - - if [ $1 = 'server' ]; then - - source "$(pwd)/lib/auto-upgrade-db.sh" - python3 "$(pwd)/lib/bootstrap.py" - - elif [ $1 = 'development-server' ]; then - - source "$(pwd)/lib/auto-upgrade-db.sh" - python3 "$(pwd)/lib/bootstrap.py" devel - - elif [ $1 = 'setup' ]; then - - source "$(pwd)/lib/setup-application.sh" - - elif [ $1 = 'generate-secret-key' ]; then - - python3 "$(pwd)/lib/generate-secret-key.py" --override - - elif [ $1 = 'force-db-upgrade' ]; then - - source "$(pwd)/lib/db-migrations.sh" - python3 "$(pwd)/lib/upgrade-db.py" - - elif [ $1 = 'create-admin' ]; then - - source "$(pwd)/lib/create-admin.sh" - - elif [ $1 = 'clear-sessions' ]; then - - source "$(pwd)/lib/clear-expired-sessions.sh" - echo -e "done." - - elif [ $1 = 'archive-tables' ]; then - - python3 "$(pwd)/lib/archive-tables.py" - - elif [ $1 = 'shell' ]; then - - source "$(pwd)/lib/start-django-shell.sh" - - elif [ $1 = 'help' ]; then - - show_dm_help 0 - - else - - show_dm_help 1 - - fi - -fi \ No newline at end of file diff --git a/scripts/bootstrap.py b/scripts/bootstrap.py new file mode 100755 index 0000000..5a9c81d --- /dev/null +++ b/scripts/bootstrap.py @@ -0,0 +1,151 @@ +#!./venv/bin/python3 +# Copyright 2023 Julian Müller (ChaoticByte) + +import os + +from argparse import ArgumentParser +from atexit import register as register_exithandler +from pathlib import Path +from signal import SIGINT +from subprocess import Popen +from sys import path as sys_path +from time import sleep + +from yaml import safe_load + + +base_directory = Path(__file__).parent.parent +data_directory = base_directory / "data" +logfile_directory = data_directory / "logs" +configuration_file = data_directory / "config.yml" +caddyfile = data_directory / "Caddyfile" +logfile_caddy = logfile_directory / "caddy.log" +logfile_app = logfile_directory / "app.log" + + +class MonitoredSubprocess: + def __init__( + self, + name: str, + commandline: list, + logfile: Path, + environment: dict = os.environ, + max_tries: int = 5, + ): + self.name = name + self.commandline = commandline + self.logfile = logfile + self.environment = environment + self.max_tries = max_tries + self.s = None # the subprocess object + self._tries = 0 + self._stopped = False + + def try_start(self): + if self._tries < self.max_tries: + self._tries += 1 + print(f"Starting {self.name}...") + with self.logfile.open("ab") as l: + self.s = Popen( + self.commandline, + stdout=l, + stderr=l, + env=self.environment) + return True + else: + print(f"Max. tries exceeded ({self.name})!") + # the process must already be stopped at this + # point, so we can set the variable accordingly + self._stopped = True + return False + + def stop(self): + if not self._stopped: + print(f"Stopping {self.name}...") + self.s.terminate() + self._stopped = True + + +def cleanup_procs(processes): + for p in processes: + p.stop() + + +if __name__ == "__main__": + argp = ArgumentParser() + argp.add_argument("--devel", help="Start development server", action="store_true") + args = argp.parse_args() + # Load configuration + with configuration_file.open("r") as f: + config = safe_load(f) + # Prepare + os.chdir(str(base_directory)) + Popen( + ["./venv/bin/python3", "./manage.py", "collectstatic", "--noinput"], env=os.environ).wait() + Popen( + ["./venv/bin/python3", "./manage.py", "migrate", "--noinput"], env=os.environ).wait() + # Start + if args.devel: + p = None + try: + p = Popen(["./venv/bin/python3", "./manage.py", "runserver"], env=os.environ).wait() + except KeyboardInterrupt: + if p is not None: + p.send_signal(SIGINT) + else: + # Caddy configuration via env + environment_caddy = os.environ + environment_caddy["DATADIR"] = str(data_directory.absolute()) + environment_caddy["HTTP_PORT"] = str(config["caddy"]["http_port"]) + environment_caddy["HTTPS_PORT"] = str(config["caddy"]["https_port"]) + environment_caddy["APPLICATION_PORT"] = str(config["app"]["application_port"]) + environment_caddy["ACCESS_LOG"] = config["logs"]["http_access"] + # Application configuration via env + environment_app = os.environ + environment_app["APP_PROD"] = "1" + print("\nRunning in production mode.\n") + # define processes + procs = [ + MonitoredSubprocess( + "Caddy Webserver", + ["caddy", "run", "--config", str(caddyfile)], + logfile_caddy, + environment=environment_caddy + ), + MonitoredSubprocess( + "Drinks-Manager", + [ + "./venv/bin/python3", + "-m", + "uvicorn", + "--host", + "127.0.0.1", + "--port", + str(config["app"]["application_port"]), + "project.asgi:application", + ], + logfile_app, + environment=environment_app + ), + ] + # start processes + for p in procs: + p.try_start() + register_exithandler(cleanup_procs, procs) + # monitor processes + try: + while True: + sleep(1) + for p in procs: + returncode = p.s.poll() + if returncode is None: + continue + else: + print(f"{p.name} stopped with exit code {returncode}.") + if p.try_start() is False: + # stop everything if the process + # has exceeded max. tries + exit() + except KeyboardInterrupt: + print("Received KeyboardInterrupt, exiting...") + exit() diff --git a/scripts/setup-env.sh b/scripts/setup-env.sh new file mode 100755 index 0000000..f700819 --- /dev/null +++ b/scripts/setup-env.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Copyright 2023 Julian Müller (ChaoticByte) + +# change to correct directory, if necessary +script_absolute=$(realpath "$0") +script_directory=$(dirname "$script_absolute") +desired_directory=$(realpath "$script_directory"/..) +if [ "$PWD" != "$desired_directory" ]; then + echo "Changing to project directory..." + cd "$desired_directory" +fi + +echo "Creating venv..." +python3 -m venv ./venv + +echo "Activating venv..." +source ./venv/bin/activate + +echo "Installing dependencies..." +python3 -m pip install -r requirements.txt diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..4fbc464 --- /dev/null +++ b/start.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +basedir=$(dirname "$0") +basedir=$(realpath $basedir) +cd "$basedir" + +export PYTHONPATH="$basedir" +export DJANGO_SETTINGS_MODULE="project.settings" +export APP_VERSION="revamp-pre" + +exec ./scripts/bootstrap.py "$@" diff --git a/static/favicon.ico b/static/favicon.ico deleted file mode 100644 index aeae09f355125794af240bdcbdb9d28efbafb251..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44425 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�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 Date: Sat, 11 Feb 2023 18:04:52 +0100 Subject: [PATCH 03/26] Fixed CSRF-related issues and profilepictures by starting caddy for development server too. Also improved boostrap script. #15 #16 --- .gitignore | 3 + app/templates/registration/login.html | 2 +- app/templates/userpanel.html | 2 +- data/Caddyfile | 2 +- data/config.example.yml | 3 +- data/profilepictures/default.svg | 28 ++++++++ project/settings.py | 5 ++ scripts/bootstrap.py | 95 ++++++++++++++++----------- 8 files changed, 99 insertions(+), 41 deletions(-) create mode 100644 data/profilepictures/default.svg diff --git a/.gitignore b/.gitignore index 794c055..b1f08b2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,12 +2,15 @@ /data/logs/* /data/tls/* /data/static/* +/data/profilepictures/* !/data/logs/ !/data/logs/.gitkeep !/data/tls/ !/data/tls/.gitkeep !/data/static/ !/data/static/.gitkeep +!/data/profilepictures/ +!/data/profilepictures/default.svg !/data/Caddyfile !/data/*.example.* diff --git a/app/templates/registration/login.html b/app/templates/registration/login.html index 4323c9e..3456582 100644 --- a/app/templates/registration/login.html +++ b/app/templates/registration/login.html @@ -69,7 +69,7 @@