diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c1d4730 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,28 @@ +FROM python:3.13-slim-bullseye + +WORKDIR /app + +RUN set -ex \ + && apt-get update \ + && apt-get install -y gettext gcc locales tzdata libpq-dev \ + && localedef -i fr_FR -c -f UTF-8 -A /usr/share/locale/locale.alias fr_FR.UTF-8 \ + && ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime \ + && dpkg-reconfigure --frontend noninteractive tzdata \ + && pip install -U pip uwsgi \ + && apt-get install -y age openssh-client \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY ./requirements.txt . +RUN pip install --no-cache -r requirements.txt + +COPY . . + +RUN chgrp -R 0 /app && \ + chmod -R g+rwX /app && \ + chmod +x docker-prestart.sh + +ENTRYPOINT ["sh", "/app/docker-prestart.sh"] + +CMD ["gunicorn", "--bind", "0.0.0.0:8002", "--workers", "3", "api.wsgi:application"] + +EXPOSE 8002 \ No newline at end of file diff --git a/api/__pycache__/urls.cpython-313.pyc b/api/__pycache__/urls.cpython-313.pyc index 78a7c05..ae023c1 100644 Binary files a/api/__pycache__/urls.cpython-313.pyc and b/api/__pycache__/urls.cpython-313.pyc differ diff --git a/api/asgi.py b/api/asgi.py deleted file mode 100644 index 46a1236..0000000 --- a/api/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for api 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/5.2/howto/deployment/asgi/ -""" - -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'api.settings') - -application = get_asgi_application() diff --git a/api/settings.py b/api/settings.py index 3f424da..975cd09 100644 --- a/api/settings.py +++ b/api/settings.py @@ -9,7 +9,7 @@ https://docs.djangoproject.com/en/5.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/5.2/ref/settings/ """ - +from os.path import normpath from pathlib import Path import os from dotenv import load_dotenv, dotenv_values @@ -25,20 +25,27 @@ BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = os.getenv("DJANGO_SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = False MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') ALLOWED_HOSTS = [ 'localhost', - '127.0.0.1' + '127.0.0.1', + '192.168.1.35', + 'guams.fr', + 'mybooklist.guams.fr', + 'mybooklist-api.guams.fr' ] CORS_ALLOWED_ORIGINS = [ "http://localhost:5173", - 'http://127.0.0.1:5173' + 'http://127.0.0.1:5173', + 'http://192.168.1.35:5173', + 'https://mybooklist.guams.fr' + 'https://mybooklist-api.guams.fr' ] @@ -69,6 +76,14 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] +MIDDLEWARE = list(MIDDLEWARE) +try: + insert_pos = MIDDLEWARE.index("django.middleware.security.SecurityMiddleware") +except ValueError: + insert_pos = 0 + +MIDDLEWARE.insert(insert_pos, "whitenoise.middleware.WhiteNoiseMiddleware") + REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_simplejwt.authentication.JWTAuthentication', @@ -148,7 +163,10 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.2/howto/static-files/ -STATIC_URL = 'static/' +BASE_DIR = Path(__file__).resolve(strict=True).parent.parent +SITE_ROOT = str(BASE_DIR) +STATIC_ROOT = normpath(os.path.join(SITE_ROOT, "assets")) +STATIC_URL = "/assets/" # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field diff --git a/books/__pycache__/views.cpython-313.pyc b/books/__pycache__/views.cpython-313.pyc index f3d122a..d4f0a81 100644 Binary files a/books/__pycache__/views.cpython-313.pyc and b/books/__pycache__/views.cpython-313.pyc differ diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml new file mode 100644 index 0000000..6fe59c6 --- /dev/null +++ b/docker-compose-dev.yml @@ -0,0 +1,17 @@ +services: + postgres: + image: postgres:17 + container_name: mblbdd + restart: always + environment: + POSTGRES_USER: pipi + POSTGRES_PASSWORD: pipi + POSTGRES_DB: pipi + ports: + - "5433:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: + driver: local diff --git a/docker-compose.yml b/docker-compose.yml index 6fe59c6..1e51fcb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,17 +1,28 @@ services: - postgres: + mbl-api: + build: + context: . + dockerfile: ./Dockerfile + restart: always + env_file: .env + volumes: + - mbl-static:/var/www/mbl-api + network_mode: host + + mbl-bdd: image: postgres:17 container_name: mblbdd restart: always environment: - POSTGRES_USER: pipi - POSTGRES_PASSWORD: pipi - POSTGRES_DB: pipi + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_NAME} ports: - - "5433:5432" + - "${DB_PORT}:5432" volumes: - postgres_data:/var/lib/postgresql/data volumes: postgres_data: driver: local + mbl-static: \ No newline at end of file diff --git a/docker-prestart.sh b/docker-prestart.sh new file mode 100644 index 0000000..28d39d8 --- /dev/null +++ b/docker-prestart.sh @@ -0,0 +1,17 @@ +#! /usr/bin/env sh +set -e +echo "Running inside /app/docker-prestart.sh" + +cd /app + +echo "Creating migrations..." +python manage.py makemigrations books +python manage.py makemigrations + +echo "Applying migrations..." +python manage.py migrate --noinput + +echo "Collecting static files..." +python manage.py collectstatic --noinput + +exec "$@" \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index fe94060..66298b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,3 +16,4 @@ psycopg = "^3.1" gunicorn = "^22.0" dotenv = "^0.9.9" pillow = "^12.0.0" +whitenoise = "^6.11.0" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..61b866f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,133 @@ +asgiref==3.11.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4 \ + --hash=sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d +django-cors-headers==4.9.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:15c7f20727f90044dcee2216a9fd7303741a864865f0c3657e28b7056f61b449 \ + --hash=sha256:fe5d7cb59fdc2c8c646ce84b727ac2bca8912a247e6e68e1fb507372178e59e8 +django==5.2.9 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:16b5ccfc5e8c27e6c0561af551d2ea32852d7352c67d452ae3e76b4f6b2ca495 \ + --hash=sha256:3a4ea88a70370557ab1930b332fd2887a9f48654261cdffda663fef5976bb00a +djangorestframework-simplejwt==5.5.1 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:2c30f3707053d384e9f315d11c2daccfcb548d4faa453111ca19a542b732e469 \ + --hash=sha256:e72c5572f51d7803021288e2057afcbd03f17fe11d484096f40a460abc76e87f +djangorestframework==3.16.1 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:166809528b1aced0a17dc66c24492af18049f2c9420dbd0be29422029cfc3ff7 \ + --hash=sha256:33a59f47fb9c85ede792cbf88bde71893bcda0667bc573f784649521f1102cec +dotenv==0.9.9 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9 +gunicorn==22.0.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9 \ + --hash=sha256:4a0b436239ff76fb33f11c07a16482c521a7e09c1ce3cc293c2330afe01bec63 +packaging==25.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \ + --hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f +pillow==12.0.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643 \ + --hash=sha256:09f2d0abef9e4e2f349305a4f8cc784a8a6c2f58a8c4892eea13b10a943bd26e \ + --hash=sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e \ + --hash=sha256:0fd00cac9c03256c8b2ff58f162ebcd2587ad3e1f2e397eab718c47e24d231cc \ + --hash=sha256:110486b79f2d112cf6add83b28b627e369219388f64ef2f960fef9ebaf54c642 \ + --hash=sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6 \ + --hash=sha256:1ac11e8ea4f611c3c0147424eae514028b5e9077dd99ab91e1bd7bc33ff145e1 \ + --hash=sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b \ + --hash=sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399 \ + --hash=sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba \ + --hash=sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad \ + --hash=sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47 \ + --hash=sha256:27f95b12453d165099c84f8a8bfdfd46b9e4bda9e0e4b65f0635430027f55739 \ + --hash=sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b \ + --hash=sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f \ + --hash=sha256:32ed80ea8a90ee3e6fa08c21e2e091bba6eda8eccc83dbc34c95169507a91f10 \ + --hash=sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52 \ + --hash=sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d \ + --hash=sha256:3adfb466bbc544b926d50fe8f4a4e6abd8c6bffd28a26177594e6e9b2b76572b \ + --hash=sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a \ + --hash=sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9 \ + --hash=sha256:455247ac8a4cfb7b9bc45b7e432d10421aea9fc2e74d285ba4072688a74c2e9d \ + --hash=sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098 \ + --hash=sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905 \ + --hash=sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b \ + --hash=sha256:5269cc1caeedb67e6f7269a42014f381f45e2e7cd42d834ede3c703a1d915fe3 \ + --hash=sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371 \ + --hash=sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953 \ + --hash=sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01 \ + --hash=sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca \ + --hash=sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e \ + --hash=sha256:6ace95230bfb7cd79ef66caa064bbe2f2a1e63d93471c3a2e1f1348d9f22d6b7 \ + --hash=sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27 \ + --hash=sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082 \ + --hash=sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e \ + --hash=sha256:759de84a33be3b178a64c8ba28ad5c135900359e85fb662bc6e403ad4407791d \ + --hash=sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8 \ + --hash=sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a \ + --hash=sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad \ + --hash=sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3 \ + --hash=sha256:805ebf596939e48dbb2e4922a1d3852cfc25c38160751ce02da93058b48d252a \ + --hash=sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d \ + --hash=sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353 \ + --hash=sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee \ + --hash=sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b \ + --hash=sha256:90387104ee8400a7b4598253b4c406f8958f59fcf983a6cea2b50d59f7d63d0b \ + --hash=sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a \ + --hash=sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7 \ + --hash=sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef \ + --hash=sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a \ + --hash=sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a \ + --hash=sha256:a3475b96f5908b3b16c47533daaa87380c491357d197564e0ba34ae75c0f3257 \ + --hash=sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07 \ + --hash=sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4 \ + --hash=sha256:aa5129de4e174daccbc59d0a3b6d20eaf24417d59851c07ebb37aeb02947987c \ + --hash=sha256:aeaefa96c768fc66818730b952a862235d68825c178f1b3ffd4efd7ad2edcb7c \ + --hash=sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4 \ + --hash=sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe \ + --hash=sha256:b22bd8c974942477156be55a768f7aa37c46904c175be4e158b6a86e3a6b7ca8 \ + --hash=sha256:b290fd8aa38422444d4b50d579de197557f182ef1068b75f5aa8558638b8d0a5 \ + --hash=sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6 \ + --hash=sha256:b583dc9070312190192631373c6c8ed277254aa6e6084b74bdd0a6d3b221608e \ + --hash=sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8 \ + --hash=sha256:bc91a56697869546d1b8f0a3ff35224557ae7f881050e99f615e0119bf934b4e \ + --hash=sha256:bd87e140e45399c818fac4247880b9ce719e4783d767e030a883a970be632275 \ + --hash=sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3 \ + --hash=sha256:bdee52571a343d721fb2eb3b090a82d959ff37fc631e3f70422e0c2e029f3e76 \ + --hash=sha256:bee2a6db3a7242ea309aa7ee8e2780726fed67ff4e5b40169f2c940e7eb09227 \ + --hash=sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9 \ + --hash=sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5 \ + --hash=sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79 \ + --hash=sha256:c7b2a63fd6d5246349f3d3f37b14430d73ee7e8173154461785e43036ffa96ca \ + --hash=sha256:c828a1ae702fc712978bda0320ba1b9893d99be0badf2647f693cc01cf0f04fa \ + --hash=sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b \ + --hash=sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e \ + --hash=sha256:cae81479f77420d217def5f54b5b9d279804d17e982e0f2fa19b1d1e14ab5197 \ + --hash=sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab \ + --hash=sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79 \ + --hash=sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2 \ + --hash=sha256:d49e2314c373f4c2b39446fb1a45ed333c850e09d0c59ac79b72eb3b95397363 \ + --hash=sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0 \ + --hash=sha256:d64317d2587c70324b79861babb9c09f71fbb780bad212018874b2c013d8600e \ + --hash=sha256:d77153e14b709fd8b8af6f66a3afbb9ed6e9fc5ccf0b6b7e1ced7b036a228782 \ + --hash=sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925 \ + --hash=sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0 \ + --hash=sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b \ + --hash=sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced \ + --hash=sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c \ + --hash=sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344 \ + --hash=sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9 \ + --hash=sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1 +psycopg==3.3.2 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:3e94bc5f4690247d734599af56e51bae8e0db8e4311ea413f801fef82b14a99b \ + --hash=sha256:707a67975ee214d200511177a6a80e56e654754c9afca06a7194ea6bbfde9ca7 +pyjwt==2.10.1 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb +python-dotenv==1.2.1 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6 \ + --hash=sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 +sqlparse==0.5.4 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:4396a7d3cf1cd679c1be976cf3dc6e0a51d0111e87787e7a8d780e7d5a998f9e \ + --hash=sha256:99a9f0314977b76d776a0fcb8554de91b9bb8a18560631d6bc48721d07023dcb +tzdata==2025.2 ; python_version >= "3.13" and python_version < "4.0" and sys_platform == "win32" \ + --hash=sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8 \ + --hash=sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9 +whitenoise==6.11.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:0f5bfce6061ae6611cd9396a8231e088722e4fc67bc13a111be74c738d99375f \ + --hash=sha256:b2aeb45950597236f53b5342b3121c5de69c8da0109362aee506ce88e022d258